mirror of
https://github.com/SFML/SFML.git
synced 2024-11-28 14:21:04 +08:00
Replace factory functions with throwing constructors
This commit is contained in:
parent
698f265277
commit
e185f6d53e
@ -21,15 +21,15 @@
|
|||||||
/// sf::RenderWindow window(sf::VideoMode({800, 600}), "SFML window");
|
/// sf::RenderWindow window(sf::VideoMode({800, 600}), "SFML window");
|
||||||
///
|
///
|
||||||
/// // Load a sprite to display
|
/// // Load a sprite to display
|
||||||
/// const auto texture = sf::Texture::loadFromFile("cute_image.jpg").value();
|
/// const sf::Texture texture("cute_image.jpg");
|
||||||
/// sf::Sprite sprite(texture);
|
/// sf::Sprite sprite(texture);
|
||||||
///
|
///
|
||||||
/// // Create a graphical text to display
|
/// // Create a graphical text to display
|
||||||
/// const auto font = sf::Font::openFromFile("arial.ttf").value();
|
/// const sf::Font font("arial.ttf");
|
||||||
/// sf::Text text(font, "Hello SFML", 50);
|
/// sf::Text text(font, "Hello SFML", 50);
|
||||||
///
|
///
|
||||||
/// // Load a music to play
|
/// // Load a music to play
|
||||||
/// auto music = sf::Music::openFromFile("nice_music.ogg").value();
|
/// sf::Music music("nice_music.ogg");
|
||||||
///
|
///
|
||||||
/// // Play the music
|
/// // Play the music
|
||||||
/// music.play();
|
/// music.play();
|
||||||
|
@ -86,13 +86,13 @@ int main(int argc, char* argv[])
|
|||||||
sf::RenderWindow window(screen, "");
|
sf::RenderWindow window(screen, "");
|
||||||
window.setFramerateLimit(30);
|
window.setFramerateLimit(30);
|
||||||
|
|
||||||
const auto texture = sf::Texture::createFromFile("image.png").value();
|
const sf::Texture texture("image.png");
|
||||||
|
|
||||||
sf::Sprite image(texture);
|
sf::Sprite image(texture);
|
||||||
image.setPosition(sf::Vector2f(screen.size) / 2.f);
|
image.setPosition(sf::Vector2f(screen.size) / 2.f);
|
||||||
image.setOrigin(sf::Vector2f(texture.getSize()) / 2.f);
|
image.setOrigin(sf::Vector2f(texture.getSize()) / 2.f);
|
||||||
|
|
||||||
const auto font = sf::Font::createFromFile("tuffy.ttf").value();
|
const sf::Font font("tuffy.ttf");
|
||||||
|
|
||||||
sf::Text text(font, "Tap anywhere to move the logo.", 64);
|
sf::Text text(font, "Tap anywhere to move the logo.", 64);
|
||||||
text.setFillColor(sf::Color::Black);
|
text.setFillColor(sf::Color::Black);
|
||||||
|
@ -52,9 +52,9 @@ struct SFMLmainWindow
|
|||||||
|
|
||||||
std::filesystem::path resPath{[[[NSBundle mainBundle] resourcePath] tostdstring]};
|
std::filesystem::path resPath{[[[NSBundle mainBundle] resourcePath] tostdstring]};
|
||||||
sf::RenderWindow renderWindow;
|
sf::RenderWindow renderWindow;
|
||||||
sf::Font font{sf::Font::createFromFile(resPath / "tuffy.ttf").value()};
|
sf::Font font{resPath / "tuffy.ttf"};
|
||||||
sf::Text text{font};
|
sf::Text text{font};
|
||||||
sf::Texture logo{sf::Texture::createFromFile(resPath / "logo.png").value()};
|
sf::Texture logo{resPath / "logo.png"};
|
||||||
sf::Sprite sprite{logo};
|
sf::Sprite sprite{logo};
|
||||||
sf::Color background{sf::Color::Blue};
|
sf::Color background{sf::Color::Blue};
|
||||||
};
|
};
|
||||||
|
@ -316,7 +316,7 @@ private:
|
|||||||
// Member data
|
// Member data
|
||||||
////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////
|
||||||
sf::RenderWindow m_window{sf::VideoMode({800u, 600u}), "SFML Event Handling", sf::Style::Titlebar | sf::Style::Close};
|
sf::RenderWindow m_window{sf::VideoMode({800u, 600u}), "SFML Event Handling", sf::Style::Titlebar | sf::Style::Close};
|
||||||
const sf::Font m_font{sf::Font::createFromFile("resources/tuffy.ttf").value()};
|
const sf::Font m_font{"resources/tuffy.ttf"};
|
||||||
sf::Text m_logText{m_font, "", 20};
|
sf::Text m_logText{m_font, "", 20};
|
||||||
sf::Text m_handlerText{m_font, "Current Handler: Classic", 24};
|
sf::Text m_handlerText{m_font, "Current Handler: Classic", 24};
|
||||||
sf::Text m_instructions{m_font, "Press Enter to change handler type", 24};
|
sf::Text m_instructions{m_font, "Press Enter to change handler type", 24};
|
||||||
|
@ -91,14 +91,14 @@ int main()
|
|||||||
sf::RenderWindow window(sf::VideoMode({windowWidth, windowHeight}), "SFML Island", sf::Style::Titlebar | sf::Style::Close);
|
sf::RenderWindow window(sf::VideoMode({windowWidth, windowHeight}), "SFML Island", sf::Style::Titlebar | sf::Style::Close);
|
||||||
window.setVerticalSyncEnabled(true);
|
window.setVerticalSyncEnabled(true);
|
||||||
|
|
||||||
const auto font = sf::Font::createFromFile("resources/tuffy.ttf").value();
|
const sf::Font font("resources/tuffy.ttf");
|
||||||
|
|
||||||
// Create all of our graphics resources
|
// Create all of our graphics resources
|
||||||
sf::Text hudText(font);
|
sf::Text hudText(font);
|
||||||
sf::Text statusText(font);
|
sf::Text statusText(font);
|
||||||
std::optional<sf::Shader> terrainShader;
|
sf::Shader terrainShader;
|
||||||
sf::RenderStates terrainStates;
|
sf::RenderStates terrainStates;
|
||||||
sf::VertexBuffer terrain(sf::PrimitiveType::Triangles, sf::VertexBuffer::Usage::Static);
|
sf::VertexBuffer terrain(sf::PrimitiveType::Triangles, sf::VertexBuffer::Usage::Static);
|
||||||
|
|
||||||
// Set up our text drawables
|
// Set up our text drawables
|
||||||
statusText.setCharacterSize(28);
|
statusText.setCharacterSize(28);
|
||||||
@ -120,7 +120,7 @@ int main()
|
|||||||
{
|
{
|
||||||
statusText.setString("Shaders and/or Vertex Buffers Unsupported");
|
statusText.setString("Shaders and/or Vertex Buffers Unsupported");
|
||||||
}
|
}
|
||||||
else if (!(terrainShader = sf::Shader::createFromFile("resources/terrain.vert", "resources/terrain.frag")))
|
else if (!terrainShader.loadFromFile("resources/terrain.vert", "resources/terrain.frag"))
|
||||||
{
|
{
|
||||||
statusText.setString("Failed to load shader program");
|
statusText.setString("Failed to load shader program");
|
||||||
}
|
}
|
||||||
@ -148,7 +148,7 @@ int main()
|
|||||||
statusText.setString("Generating Terrain...");
|
statusText.setString("Generating Terrain...");
|
||||||
|
|
||||||
// Set up the render states
|
// Set up the render states
|
||||||
terrainStates = sf::RenderStates(&*terrainShader);
|
terrainStates = sf::RenderStates(&terrainShader);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Center the status text
|
// Center the status text
|
||||||
@ -186,7 +186,8 @@ int main()
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Arrow key pressed:
|
// Arrow key pressed:
|
||||||
if (terrainShader.has_value() && event->is<sf::Event::KeyPressed>())
|
// TODO Replace use of getNativeHandle() when validity function is added
|
||||||
|
if (terrainShader.getNativeHandle() != 0 && event->is<sf::Event::KeyPressed>())
|
||||||
{
|
{
|
||||||
switch (event->getIf<sf::Event::KeyPressed>()->code)
|
switch (event->getIf<sf::Event::KeyPressed>()->code)
|
||||||
{
|
{
|
||||||
@ -216,7 +217,7 @@ int main()
|
|||||||
|
|
||||||
window.draw(statusText);
|
window.draw(statusText);
|
||||||
|
|
||||||
if (terrainShader.has_value())
|
if (terrainShader.getNativeHandle() != 0)
|
||||||
{
|
{
|
||||||
{
|
{
|
||||||
const std::lock_guard lock(workQueueMutex);
|
const std::lock_guard lock(workQueueMutex);
|
||||||
@ -236,7 +237,7 @@ int main()
|
|||||||
bufferUploadPending = false;
|
bufferUploadPending = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
terrainShader->setUniform("lightFactor", lightFactor);
|
terrainShader.setUniform("lightFactor", lightFactor);
|
||||||
window.draw(terrain, terrainStates);
|
window.draw(terrain, terrainStates);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -94,7 +94,7 @@ int main()
|
|||||||
window.setVerticalSyncEnabled(true);
|
window.setVerticalSyncEnabled(true);
|
||||||
|
|
||||||
// Open the text font
|
// Open the text font
|
||||||
const auto font = sf::Font::createFromFile("resources/tuffy.ttf").value();
|
const sf::Font font("resources/tuffy.ttf");
|
||||||
|
|
||||||
// Set up our string conversion parameters
|
// Set up our string conversion parameters
|
||||||
sstr.precision(2);
|
sstr.precision(2);
|
||||||
|
@ -58,11 +58,11 @@ int main()
|
|||||||
window.setMaximumSize(sf::Vector2u(1200, 900));
|
window.setMaximumSize(sf::Vector2u(1200, 900));
|
||||||
|
|
||||||
// Create a sprite for the background
|
// Create a sprite for the background
|
||||||
const auto backgroundTexture = sf::Texture::createFromFile(resourcesDir() / "background.jpg", sRgb).value();
|
const sf::Texture backgroundTexture(resourcesDir() / "background.jpg", sRgb);
|
||||||
const sf::Sprite background(backgroundTexture);
|
const sf::Sprite background(backgroundTexture);
|
||||||
|
|
||||||
// Create some text to draw on top of our OpenGL object
|
// Create some text to draw on top of our OpenGL object
|
||||||
const auto font = sf::Font::createFromFile(resourcesDir() / "tuffy.ttf").value();
|
const sf::Font font(resourcesDir() / "tuffy.ttf");
|
||||||
|
|
||||||
sf::Text text(font, "SFML / OpenGL demo");
|
sf::Text text(font, "SFML / OpenGL demo");
|
||||||
sf::Text sRgbInstructions(font, "Press space to toggle sRGB conversion");
|
sf::Text sRgbInstructions(font, "Press space to toggle sRGB conversion");
|
||||||
@ -75,7 +75,7 @@ int main()
|
|||||||
mipmapInstructions.setPosition({200.f, 550.f});
|
mipmapInstructions.setPosition({200.f, 550.f});
|
||||||
|
|
||||||
// Load a texture to apply to our 3D cube
|
// Load a texture to apply to our 3D cube
|
||||||
auto texture = sf::Texture::createFromFile(resourcesDir() / "logo.png").value();
|
sf::Texture texture(resourcesDir() / "logo.png");
|
||||||
|
|
||||||
// Attempt to generate a mipmap for our cube texture
|
// Attempt to generate a mipmap for our cube texture
|
||||||
// We don't check the return value here since
|
// We don't check the return value here since
|
||||||
@ -219,7 +219,7 @@ int main()
|
|||||||
if (mipmapEnabled)
|
if (mipmapEnabled)
|
||||||
{
|
{
|
||||||
// We simply reload the texture to disable mipmapping
|
// We simply reload the texture to disable mipmapping
|
||||||
texture = sf::Texture::createFromFile(resourcesDir() / "logo.png").value();
|
texture = sf::Texture(resourcesDir() / "logo.png");
|
||||||
|
|
||||||
// Rebind the texture
|
// Rebind the texture
|
||||||
sf::Texture::bind(&texture);
|
sf::Texture::bind(&texture);
|
||||||
|
@ -19,7 +19,7 @@ int main()
|
|||||||
window.setVerticalSyncEnabled(true);
|
window.setVerticalSyncEnabled(true);
|
||||||
|
|
||||||
// Open the application font
|
// Open the application font
|
||||||
const auto font = sf::Font::createFromFile("resources/tuffy.ttf").value();
|
const sf::Font font("resources/tuffy.ttf");
|
||||||
|
|
||||||
// Create the mouse position text
|
// Create the mouse position text
|
||||||
sf::Text mousePosition(font, "", 20);
|
sf::Text mousePosition(font, "", 20);
|
||||||
|
@ -278,69 +278,66 @@ private:
|
|||||||
////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////
|
||||||
std::optional<Pixelate> tryLoadPixelate()
|
std::optional<Pixelate> tryLoadPixelate()
|
||||||
{
|
{
|
||||||
auto texture = sf::Texture::createFromFile("resources/background.jpg");
|
sf::Texture texture;
|
||||||
if (!texture.has_value())
|
if (!texture.loadFromFile("resources/background.jpg"))
|
||||||
return std::nullopt;
|
return std::nullopt;
|
||||||
|
|
||||||
auto shader = sf::Shader::createFromFile("resources/pixelate.frag", sf::Shader::Type::Fragment);
|
sf::Shader shader;
|
||||||
if (!shader.has_value())
|
if (!shader.loadFromFile("resources/pixelate.frag", sf::Shader::Type::Fragment))
|
||||||
return std::nullopt;
|
return std::nullopt;
|
||||||
|
|
||||||
return std::make_optional<Pixelate>(std::move(*texture), std::move(*shader));
|
return std::make_optional<Pixelate>(std::move(texture), std::move(shader));
|
||||||
}
|
}
|
||||||
|
|
||||||
std::optional<WaveBlur> tryLoadWaveBlur(const sf::Font& font)
|
std::optional<WaveBlur> tryLoadWaveBlur(const sf::Font& font)
|
||||||
{
|
{
|
||||||
auto shader = sf::Shader::createFromFile("resources/wave.vert", "resources/blur.frag");
|
sf::Shader shader;
|
||||||
if (!shader.has_value())
|
if (!shader.loadFromFile("resources/wave.vert", "resources/blur.frag"))
|
||||||
return std::nullopt;
|
return std::nullopt;
|
||||||
|
|
||||||
return std::make_optional<WaveBlur>(font, std::move(*shader));
|
return std::make_optional<WaveBlur>(font, std::move(shader));
|
||||||
}
|
}
|
||||||
|
|
||||||
std::optional<StormBlink> tryLoadStormBlink()
|
std::optional<StormBlink> tryLoadStormBlink()
|
||||||
{
|
{
|
||||||
auto shader = sf::Shader::createFromFile("resources/storm.vert", "resources/blink.frag");
|
sf::Shader shader;
|
||||||
if (!shader.has_value())
|
if (!shader.loadFromFile("resources/storm.vert", "resources/blink.frag"))
|
||||||
return std::nullopt;
|
return std::nullopt;
|
||||||
|
|
||||||
return std::make_optional<StormBlink>(std::move(*shader));
|
return std::make_optional<StormBlink>(std::move(shader));
|
||||||
}
|
}
|
||||||
|
|
||||||
std::optional<Edge> tryLoadEdge()
|
std::optional<Edge> tryLoadEdge()
|
||||||
{
|
{
|
||||||
// Create the off-screen surface
|
// Create the off-screen surface
|
||||||
auto surface = sf::RenderTexture::create({800, 600});
|
sf::RenderTexture surface;
|
||||||
if (!surface.has_value())
|
if (!surface.resize({800, 600}))
|
||||||
return std::nullopt;
|
return std::nullopt;
|
||||||
|
|
||||||
surface->setSmooth(true);
|
surface.setSmooth(true);
|
||||||
|
|
||||||
// Load the background texture
|
// Load the background texture
|
||||||
auto backgroundTexture = sf::Texture::createFromFile("resources/sfml.png");
|
sf::Texture backgroundTexture;
|
||||||
if (!backgroundTexture.has_value())
|
if (!backgroundTexture.loadFromFile("resources/sfml.png"))
|
||||||
return std::nullopt;
|
return std::nullopt;
|
||||||
|
|
||||||
backgroundTexture->setSmooth(true);
|
backgroundTexture.setSmooth(true);
|
||||||
|
|
||||||
// Load the entity texture
|
// Load the entity texture
|
||||||
auto entityTexture = sf::Texture::createFromFile("resources/devices.png");
|
sf::Texture entityTexture;
|
||||||
if (!entityTexture.has_value())
|
if (!entityTexture.loadFromFile("resources/devices.png"))
|
||||||
return std::nullopt;
|
return std::nullopt;
|
||||||
|
|
||||||
entityTexture->setSmooth(true);
|
entityTexture.setSmooth(true);
|
||||||
|
|
||||||
// Load the shader
|
// Load the shader
|
||||||
auto shader = sf::Shader::createFromFile("resources/edge.frag", sf::Shader::Type::Fragment);
|
sf::Shader shader;
|
||||||
if (!shader.has_value())
|
if (!shader.loadFromFile("resources/edge.frag", sf::Shader::Type::Fragment))
|
||||||
return std::nullopt;
|
return std::nullopt;
|
||||||
|
|
||||||
shader->setUniform("texture", sf::Shader::CurrentTexture);
|
shader.setUniform("texture", sf::Shader::CurrentTexture);
|
||||||
|
|
||||||
return std::make_optional<Edge>(std::move(*surface),
|
return std::make_optional<Edge>(std::move(surface), std::move(backgroundTexture), std::move(entityTexture), std::move(shader));
|
||||||
std::move(*backgroundTexture),
|
|
||||||
std::move(*entityTexture),
|
|
||||||
std::move(*shader));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
std::optional<Geometry> tryLoadGeometry()
|
std::optional<Geometry> tryLoadGeometry()
|
||||||
@ -350,25 +347,23 @@ std::optional<Geometry> tryLoadGeometry()
|
|||||||
return std::nullopt;
|
return std::nullopt;
|
||||||
|
|
||||||
// Load the logo texture
|
// Load the logo texture
|
||||||
auto logoTexture = sf::Texture::createFromFile("resources/logo.png");
|
sf::Texture logoTexture;
|
||||||
if (!logoTexture.has_value())
|
if (!logoTexture.loadFromFile("resources/logo.png"))
|
||||||
return std::nullopt;
|
return std::nullopt;
|
||||||
|
|
||||||
logoTexture->setSmooth(true);
|
logoTexture.setSmooth(true);
|
||||||
|
|
||||||
// Load the shader
|
// Load the shader
|
||||||
auto shader = sf::Shader::createFromFile("resources/billboard.vert",
|
sf::Shader shader;
|
||||||
"resources/billboard.geom",
|
if (!shader.loadFromFile("resources/billboard.vert", "resources/billboard.geom", "resources/billboard.frag"))
|
||||||
"resources/billboard.frag");
|
|
||||||
if (!shader.has_value())
|
|
||||||
return std::nullopt;
|
return std::nullopt;
|
||||||
|
|
||||||
shader->setUniform("texture", sf::Shader::CurrentTexture);
|
shader.setUniform("texture", sf::Shader::CurrentTexture);
|
||||||
|
|
||||||
// Set the render resolution (used for proper scaling)
|
// Set the render resolution (used for proper scaling)
|
||||||
shader->setUniform("resolution", sf::Vector2f(800, 600));
|
shader.setUniform("resolution", sf::Vector2f(800, 600));
|
||||||
|
|
||||||
return std::make_optional<Geometry>(std::move(*logoTexture), std::move(*shader));
|
return std::make_optional<Geometry>(std::move(logoTexture), std::move(shader));
|
||||||
}
|
}
|
||||||
|
|
||||||
} // namespace
|
} // namespace
|
||||||
@ -394,7 +389,7 @@ int main()
|
|||||||
window.setVerticalSyncEnabled(true);
|
window.setVerticalSyncEnabled(true);
|
||||||
|
|
||||||
// Open the application font
|
// Open the application font
|
||||||
const auto font = sf::Font::createFromFile("resources/tuffy.ttf").value();
|
const sf::Font font("resources/tuffy.ttf");
|
||||||
|
|
||||||
// Create the effects
|
// Create the effects
|
||||||
std::optional pixelateEffect = tryLoadPixelate();
|
std::optional pixelateEffect = tryLoadPixelate();
|
||||||
@ -418,8 +413,8 @@ int main()
|
|||||||
std::size_t current = 0;
|
std::size_t current = 0;
|
||||||
|
|
||||||
// Create the messages background
|
// Create the messages background
|
||||||
const auto textBackgroundTexture = sf::Texture::createFromFile("resources/text-background.png").value();
|
const sf::Texture textBackgroundTexture("resources/text-background.png");
|
||||||
sf::Sprite textBackground(textBackgroundTexture);
|
sf::Sprite textBackground(textBackgroundTexture);
|
||||||
textBackground.setPosition({0.f, 520.f});
|
textBackground.setPosition({0.f, 520.f});
|
||||||
textBackground.setColor(sf::Color(255, 255, 255, 200));
|
textBackground.setColor(sf::Color(255, 255, 255, 200));
|
||||||
|
|
||||||
|
@ -13,7 +13,7 @@
|
|||||||
void playSound()
|
void playSound()
|
||||||
{
|
{
|
||||||
// Load a sound buffer from a wav file
|
// Load a sound buffer from a wav file
|
||||||
const auto buffer = sf::SoundBuffer::createFromFile("resources/killdeer.wav").value();
|
const sf::SoundBuffer buffer("resources/killdeer.wav");
|
||||||
|
|
||||||
// Display sound information
|
// Display sound information
|
||||||
std::cout << "killdeer.wav:" << '\n'
|
std::cout << "killdeer.wav:" << '\n'
|
||||||
@ -46,7 +46,7 @@ void playSound()
|
|||||||
void playMusic(const std::filesystem::path& filename)
|
void playMusic(const std::filesystem::path& filename)
|
||||||
{
|
{
|
||||||
// Load an ogg music file
|
// Load an ogg music file
|
||||||
auto music = sf::Music::createFromFile("resources" / filename).value();
|
sf::Music music("resources" / filename);
|
||||||
|
|
||||||
// Display music information
|
// Display music information
|
||||||
std::cout << filename << ":" << '\n'
|
std::cout << filename << ":" << '\n'
|
||||||
|
@ -115,23 +115,23 @@ public:
|
|||||||
m_listener.setFillColor(sf::Color::Red);
|
m_listener.setFillColor(sf::Color::Red);
|
||||||
|
|
||||||
// Load the music file
|
// Load the music file
|
||||||
if (!(m_music = sf::Music::createFromFile(resourcesDir() / "doodle_pop.ogg")))
|
if (!m_music.openFromFile(resourcesDir() / "doodle_pop.ogg"))
|
||||||
{
|
{
|
||||||
std::cerr << "Failed to load " << (resourcesDir() / "doodle_pop.ogg").string() << std::endl;
|
std::cerr << "Failed to load " << (resourcesDir() / "doodle_pop.ogg").string() << std::endl;
|
||||||
std::abort();
|
std::abort();
|
||||||
}
|
}
|
||||||
|
|
||||||
// Set the music to loop
|
// Set the music to loop
|
||||||
m_music->setLoop(true);
|
m_music.setLoop(true);
|
||||||
|
|
||||||
// Set attenuation to a nice value
|
// Set attenuation to a nice value
|
||||||
m_music->setAttenuation(0.04f);
|
m_music.setAttenuation(0.04f);
|
||||||
}
|
}
|
||||||
|
|
||||||
void onUpdate(float /*time*/, float x, float y) override
|
void onUpdate(float /*time*/, float x, float y) override
|
||||||
{
|
{
|
||||||
m_position = {windowWidth * x - 10.f, windowHeight * y - 10.f};
|
m_position = {windowWidth * x - 10.f, windowHeight * y - 10.f};
|
||||||
m_music->setPosition({m_position.x, m_position.y, 0.f});
|
m_music.setPosition({m_position.x, m_position.y, 0.f});
|
||||||
}
|
}
|
||||||
|
|
||||||
void onDraw(sf::RenderTarget& target, sf::RenderStates states) const override
|
void onDraw(sf::RenderTarget& target, sf::RenderStates states) const override
|
||||||
@ -149,19 +149,19 @@ public:
|
|||||||
// Synchronize listener audio position with graphical position
|
// Synchronize listener audio position with graphical position
|
||||||
sf::Listener::setPosition({m_listener.getPosition().x, m_listener.getPosition().y, 0.f});
|
sf::Listener::setPosition({m_listener.getPosition().x, m_listener.getPosition().y, 0.f});
|
||||||
|
|
||||||
m_music->play();
|
m_music.play();
|
||||||
}
|
}
|
||||||
|
|
||||||
void onStop() override
|
void onStop() override
|
||||||
{
|
{
|
||||||
m_music->stop();
|
m_music.stop();
|
||||||
}
|
}
|
||||||
|
|
||||||
private:
|
private:
|
||||||
sf::CircleShape m_listener{20.f};
|
sf::CircleShape m_listener{20.f};
|
||||||
sf::CircleShape m_soundShape{20.f};
|
sf::CircleShape m_soundShape{20.f};
|
||||||
sf::Vector2f m_position;
|
sf::Vector2f m_position;
|
||||||
std::optional<sf::Music> m_music;
|
sf::Music m_music;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
@ -177,23 +177,23 @@ public:
|
|||||||
m_volumeText(getFont(), "Volume: " + std::to_string(m_volume))
|
m_volumeText(getFont(), "Volume: " + std::to_string(m_volume))
|
||||||
{
|
{
|
||||||
// Load the music file
|
// Load the music file
|
||||||
if (!(m_music = sf::Music::createFromFile(resourcesDir() / "doodle_pop.ogg")))
|
if (!m_music.openFromFile(resourcesDir() / "doodle_pop.ogg"))
|
||||||
{
|
{
|
||||||
std::cerr << "Failed to load " << (resourcesDir() / "doodle_pop.ogg").string() << std::endl;
|
std::cerr << "Failed to load " << (resourcesDir() / "doodle_pop.ogg").string() << std::endl;
|
||||||
std::abort();
|
std::abort();
|
||||||
}
|
}
|
||||||
|
|
||||||
// Set the music to loop
|
// Set the music to loop
|
||||||
m_music->setLoop(true);
|
m_music.setLoop(true);
|
||||||
|
|
||||||
// We don't care about attenuation in this effect
|
// We don't care about attenuation in this effect
|
||||||
m_music->setAttenuation(0.f);
|
m_music.setAttenuation(0.f);
|
||||||
|
|
||||||
// Set initial pitch
|
// Set initial pitch
|
||||||
m_music->setPitch(m_pitch);
|
m_music.setPitch(m_pitch);
|
||||||
|
|
||||||
// Set initial volume
|
// Set initial volume
|
||||||
m_music->setVolume(m_volume);
|
m_music.setVolume(m_volume);
|
||||||
|
|
||||||
m_pitchText.setPosition({windowWidth / 2.f - 120.f, windowHeight / 2.f - 80.f});
|
m_pitchText.setPosition({windowWidth / 2.f - 120.f, windowHeight / 2.f - 80.f});
|
||||||
m_volumeText.setPosition({windowWidth / 2.f - 120.f, windowHeight / 2.f - 30.f});
|
m_volumeText.setPosition({windowWidth / 2.f - 120.f, windowHeight / 2.f - 30.f});
|
||||||
@ -204,8 +204,8 @@ public:
|
|||||||
m_pitch = std::clamp(2.f * x, 0.f, 2.f);
|
m_pitch = std::clamp(2.f * x, 0.f, 2.f);
|
||||||
m_volume = std::clamp(100.f * (1.f - y), 0.f, 100.f);
|
m_volume = std::clamp(100.f * (1.f - y), 0.f, 100.f);
|
||||||
|
|
||||||
m_music->setPitch(m_pitch);
|
m_music.setPitch(m_pitch);
|
||||||
m_music->setVolume(m_volume);
|
m_music.setVolume(m_volume);
|
||||||
|
|
||||||
m_pitchText.setString("Pitch: " + std::to_string(m_pitch));
|
m_pitchText.setString("Pitch: " + std::to_string(m_pitch));
|
||||||
m_volumeText.setString("Volume: " + std::to_string(m_volume));
|
m_volumeText.setString("Volume: " + std::to_string(m_volume));
|
||||||
@ -223,20 +223,20 @@ public:
|
|||||||
// so that the music is right on top of the listener
|
// so that the music is right on top of the listener
|
||||||
sf::Listener::setPosition({0.f, 0.f, 0.f});
|
sf::Listener::setPosition({0.f, 0.f, 0.f});
|
||||||
|
|
||||||
m_music->play();
|
m_music.play();
|
||||||
}
|
}
|
||||||
|
|
||||||
void onStop() override
|
void onStop() override
|
||||||
{
|
{
|
||||||
m_music->stop();
|
m_music.stop();
|
||||||
}
|
}
|
||||||
|
|
||||||
private:
|
private:
|
||||||
float m_pitch{1.f};
|
float m_pitch{1.f};
|
||||||
float m_volume{100.f};
|
float m_volume{100.f};
|
||||||
sf::Text m_pitchText;
|
sf::Text m_pitchText;
|
||||||
sf::Text m_volumeText;
|
sf::Text m_volumeText;
|
||||||
std::optional<sf::Music> m_music;
|
sf::Music m_music;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
@ -283,23 +283,23 @@ public:
|
|||||||
makeCone(m_soundConeInner, innerConeAngle);
|
makeCone(m_soundConeInner, innerConeAngle);
|
||||||
|
|
||||||
// Load the music file
|
// Load the music file
|
||||||
if (!(m_music = sf::Music::createFromFile(resourcesDir() / "doodle_pop.ogg")))
|
if (!m_music.openFromFile(resourcesDir() / "doodle_pop.ogg"))
|
||||||
{
|
{
|
||||||
std::cerr << "Failed to load " << (resourcesDir() / "doodle_pop.ogg").string() << std::endl;
|
std::cerr << "Failed to load " << (resourcesDir() / "doodle_pop.ogg").string() << std::endl;
|
||||||
std::abort();
|
std::abort();
|
||||||
}
|
}
|
||||||
|
|
||||||
// Set the music to loop
|
// Set the music to loop
|
||||||
m_music->setLoop(true);
|
m_music.setLoop(true);
|
||||||
|
|
||||||
// Set attenuation factor
|
// Set attenuation factor
|
||||||
m_music->setAttenuation(m_attenuation);
|
m_music.setAttenuation(m_attenuation);
|
||||||
|
|
||||||
// Set direction to face "downwards"
|
// Set direction to face "downwards"
|
||||||
m_music->setDirection({0.f, 1.f, 0.f});
|
m_music.setDirection({0.f, 1.f, 0.f});
|
||||||
|
|
||||||
// Set cone
|
// Set cone
|
||||||
m_music->setCone({innerConeAngle, outerConeAngle, 0.f});
|
m_music.setCone({innerConeAngle, outerConeAngle, 0.f});
|
||||||
|
|
||||||
m_text.setString(
|
m_text.setString(
|
||||||
"Attenuation factor dampens full volume of sound while within inner cone based on distance to "
|
"Attenuation factor dampens full volume of sound while within inner cone based on distance to "
|
||||||
@ -314,7 +314,7 @@ public:
|
|||||||
void onUpdate(float /*time*/, float x, float y) override
|
void onUpdate(float /*time*/, float x, float y) override
|
||||||
{
|
{
|
||||||
m_position = {windowWidth * x - 10.f, windowHeight * y - 10.f};
|
m_position = {windowWidth * x - 10.f, windowHeight * y - 10.f};
|
||||||
m_music->setPosition({m_position.x, m_position.y, 0.f});
|
m_music.setPosition({m_position.x, m_position.y, 0.f});
|
||||||
}
|
}
|
||||||
|
|
||||||
void onDraw(sf::RenderTarget& target, sf::RenderStates states) const override
|
void onDraw(sf::RenderTarget& target, sf::RenderStates states) const override
|
||||||
@ -336,22 +336,22 @@ public:
|
|||||||
// Synchronize listener audio position with graphical position
|
// Synchronize listener audio position with graphical position
|
||||||
sf::Listener::setPosition({m_listener.getPosition().x, m_listener.getPosition().y, 0.f});
|
sf::Listener::setPosition({m_listener.getPosition().x, m_listener.getPosition().y, 0.f});
|
||||||
|
|
||||||
m_music->play();
|
m_music.play();
|
||||||
}
|
}
|
||||||
|
|
||||||
void onStop() override
|
void onStop() override
|
||||||
{
|
{
|
||||||
m_music->stop();
|
m_music.stop();
|
||||||
}
|
}
|
||||||
|
|
||||||
private:
|
private:
|
||||||
sf::CircleShape m_listener{20.f};
|
sf::CircleShape m_listener{20.f};
|
||||||
sf::CircleShape m_soundShape{20.f};
|
sf::CircleShape m_soundShape{20.f};
|
||||||
sf::ConvexShape m_soundConeOuter;
|
sf::ConvexShape m_soundConeOuter;
|
||||||
sf::ConvexShape m_soundConeInner;
|
sf::ConvexShape m_soundConeInner;
|
||||||
sf::Text m_text;
|
sf::Text m_text;
|
||||||
sf::Vector2f m_position;
|
sf::Vector2f m_position;
|
||||||
std::optional<sf::Music> m_music;
|
sf::Music m_music;
|
||||||
|
|
||||||
float m_attenuation{0.01f};
|
float m_attenuation{0.01f};
|
||||||
};
|
};
|
||||||
@ -636,7 +636,7 @@ public:
|
|||||||
void onUpdate([[maybe_unused]] float time, float x, float y) override
|
void onUpdate([[maybe_unused]] float time, float x, float y) override
|
||||||
{
|
{
|
||||||
m_position = {windowWidth * x - 10.f, windowHeight * y - 10.f};
|
m_position = {windowWidth * x - 10.f, windowHeight * y - 10.f};
|
||||||
m_music->setPosition({m_position.x, m_position.y, 0.f});
|
m_music.setPosition({m_position.x, m_position.y, 0.f});
|
||||||
}
|
}
|
||||||
|
|
||||||
void onDraw(sf::RenderTarget& target, sf::RenderStates states) const override
|
void onDraw(sf::RenderTarget& target, sf::RenderStates states) const override
|
||||||
@ -656,12 +656,12 @@ public:
|
|||||||
// Synchronize listener audio position with graphical position
|
// Synchronize listener audio position with graphical position
|
||||||
sf::Listener::setPosition({m_listener.getPosition().x, m_listener.getPosition().y, 0.f});
|
sf::Listener::setPosition({m_listener.getPosition().x, m_listener.getPosition().y, 0.f});
|
||||||
|
|
||||||
m_music->play();
|
m_music.play();
|
||||||
}
|
}
|
||||||
|
|
||||||
void onStop() override
|
void onStop() override
|
||||||
{
|
{
|
||||||
m_music->stop();
|
m_music.stop();
|
||||||
}
|
}
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
@ -677,22 +677,22 @@ protected:
|
|||||||
m_instructions.setPosition({windowWidth / 2.f - 250.f, windowHeight * 3.f / 4.f});
|
m_instructions.setPosition({windowWidth / 2.f - 250.f, windowHeight * 3.f / 4.f});
|
||||||
|
|
||||||
// Load the music file
|
// Load the music file
|
||||||
if (!(m_music = sf::Music::createFromFile(resourcesDir() / "doodle_pop.ogg")))
|
if (!m_music.openFromFile(resourcesDir() / "doodle_pop.ogg"))
|
||||||
{
|
{
|
||||||
std::cerr << "Failed to load " << (resourcesDir() / "doodle_pop.ogg").string() << std::endl;
|
std::cerr << "Failed to load " << (resourcesDir() / "doodle_pop.ogg").string() << std::endl;
|
||||||
std::abort();
|
std::abort();
|
||||||
}
|
}
|
||||||
|
|
||||||
// Set the music to loop
|
// Set the music to loop
|
||||||
m_music->setLoop(true);
|
m_music.setLoop(true);
|
||||||
|
|
||||||
// Set attenuation to a nice value
|
// Set attenuation to a nice value
|
||||||
m_music->setAttenuation(0.0f);
|
m_music.setAttenuation(0.0f);
|
||||||
}
|
}
|
||||||
|
|
||||||
sf::Music& getMusic()
|
sf::Music& getMusic()
|
||||||
{
|
{
|
||||||
return *m_music;
|
return m_music;
|
||||||
}
|
}
|
||||||
|
|
||||||
const std::shared_ptr<bool>& getEnabled() const
|
const std::shared_ptr<bool>& getEnabled() const
|
||||||
@ -709,13 +709,13 @@ private:
|
|||||||
m_enabledText.setString(*m_enabled ? "Processing: Enabled" : "Processing: Disabled");
|
m_enabledText.setString(*m_enabled ? "Processing: Enabled" : "Processing: Disabled");
|
||||||
}
|
}
|
||||||
|
|
||||||
sf::CircleShape m_listener{20.f};
|
sf::CircleShape m_listener{20.f};
|
||||||
sf::CircleShape m_soundShape{20.f};
|
sf::CircleShape m_soundShape{20.f};
|
||||||
sf::Vector2f m_position;
|
sf::Vector2f m_position;
|
||||||
std::optional<sf::Music> m_music;
|
sf::Music m_music;
|
||||||
std::shared_ptr<bool> m_enabled{std::make_shared<bool>(true)};
|
std::shared_ptr<bool> m_enabled{std::make_shared<bool>(true)};
|
||||||
sf::Text m_enabledText;
|
sf::Text m_enabledText;
|
||||||
sf::Text m_instructions;
|
sf::Text m_instructions;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
@ -1077,7 +1077,7 @@ int main()
|
|||||||
window.setVerticalSyncEnabled(true);
|
window.setVerticalSyncEnabled(true);
|
||||||
|
|
||||||
// Open the application font and pass it to the Effect class
|
// Open the application font and pass it to the Effect class
|
||||||
const auto font = sf::Font::createFromFile(resourcesDir() / "tuffy.ttf").value();
|
const sf::Font font(resourcesDir() / "tuffy.ttf");
|
||||||
Effect::setFont(font);
|
Effect::setFont(font);
|
||||||
|
|
||||||
// Create the effects
|
// Create the effects
|
||||||
@ -1106,8 +1106,8 @@ int main()
|
|||||||
effects[current]->start();
|
effects[current]->start();
|
||||||
|
|
||||||
// Create the messages background
|
// Create the messages background
|
||||||
const auto textBackgroundTexture = sf::Texture::createFromFile(resourcesDir() / "text-background.png").value();
|
const sf::Texture textBackgroundTexture(resourcesDir() / "text-background.png");
|
||||||
sf::Sprite textBackground(textBackgroundTexture);
|
sf::Sprite textBackground(textBackgroundTexture);
|
||||||
textBackground.setPosition({0.f, 520.f});
|
textBackground.setPosition({0.f, 520.f});
|
||||||
textBackground.setColor(sf::Color(255, 255, 255, 200));
|
textBackground.setColor(sf::Color(255, 255, 255, 200));
|
||||||
|
|
||||||
|
@ -49,12 +49,12 @@ int main()
|
|||||||
window.setVerticalSyncEnabled(true);
|
window.setVerticalSyncEnabled(true);
|
||||||
|
|
||||||
// Load the sounds used in the game
|
// Load the sounds used in the game
|
||||||
const auto ballSoundBuffer = sf::SoundBuffer::createFromFile(resourcesDir() / "ball.wav").value();
|
const sf::SoundBuffer ballSoundBuffer(resourcesDir() / "ball.wav");
|
||||||
sf::Sound ballSound(ballSoundBuffer);
|
sf::Sound ballSound(ballSoundBuffer);
|
||||||
|
|
||||||
// Create the SFML logo texture:
|
// Create the SFML logo texture:
|
||||||
const auto sfmlLogoTexture = sf::Texture::createFromFile(resourcesDir() / "sfml_logo.png").value();
|
const sf::Texture sfmlLogoTexture(resourcesDir() / "sfml_logo.png");
|
||||||
sf::Sprite sfmlLogo(sfmlLogoTexture);
|
sf::Sprite sfmlLogo(sfmlLogoTexture);
|
||||||
sfmlLogo.setPosition({170.f, 50.f});
|
sfmlLogo.setPosition({170.f, 50.f});
|
||||||
|
|
||||||
// Create the left paddle
|
// Create the left paddle
|
||||||
@ -82,7 +82,7 @@ int main()
|
|||||||
ball.setOrigin({ballRadius / 2.f, ballRadius / 2.f});
|
ball.setOrigin({ballRadius / 2.f, ballRadius / 2.f});
|
||||||
|
|
||||||
// Open the text font
|
// Open the text font
|
||||||
const auto font = sf::Font::createFromFile(resourcesDir() / "tuffy.ttf").value();
|
const sf::Font font(resourcesDir() / "tuffy.ttf");
|
||||||
|
|
||||||
// Initialize the pause message
|
// Initialize the pause message
|
||||||
sf::Text pauseMessage(font);
|
sf::Text pauseMessage(font);
|
||||||
|
@ -923,17 +923,17 @@ public:
|
|||||||
|
|
||||||
// Use the vertex shader SPIR-V code to create a vertex shader module
|
// Use the vertex shader SPIR-V code to create a vertex shader module
|
||||||
{
|
{
|
||||||
auto file = sf::FileInputStream::create("resources/shader.vert.spv");
|
sf::FileInputStream file;
|
||||||
if (!file)
|
if (!file.open("resources/shader.vert.spv"))
|
||||||
{
|
{
|
||||||
vulkanAvailable = false;
|
vulkanAvailable = false;
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
const auto fileSize = file->getSize().value();
|
const auto fileSize = file.getSize().value();
|
||||||
std::vector<std::uint32_t> buffer(fileSize / sizeof(std::uint32_t));
|
std::vector<std::uint32_t> buffer(fileSize / sizeof(std::uint32_t));
|
||||||
|
|
||||||
if (file->read(buffer.data(), fileSize) != file->getSize())
|
if (file.read(buffer.data(), fileSize) != file.getSize())
|
||||||
{
|
{
|
||||||
vulkanAvailable = false;
|
vulkanAvailable = false;
|
||||||
return;
|
return;
|
||||||
@ -951,17 +951,17 @@ public:
|
|||||||
|
|
||||||
// Use the fragment shader SPIR-V code to create a fragment shader module
|
// Use the fragment shader SPIR-V code to create a fragment shader module
|
||||||
{
|
{
|
||||||
auto file = sf::FileInputStream::create("resources/shader.frag.spv");
|
sf::FileInputStream file;
|
||||||
if (!file)
|
if (!file.open("resources/shader.frag.spv"))
|
||||||
{
|
{
|
||||||
vulkanAvailable = false;
|
vulkanAvailable = false;
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
const auto fileSize = file->getSize().value();
|
const auto fileSize = file.getSize().value();
|
||||||
std::vector<std::uint32_t> buffer(fileSize / sizeof(std::uint32_t));
|
std::vector<std::uint32_t> buffer(fileSize / sizeof(std::uint32_t));
|
||||||
|
|
||||||
if (file->read(buffer.data(), fileSize) != file->getSize())
|
if (file.read(buffer.data(), fileSize) != file.getSize())
|
||||||
{
|
{
|
||||||
vulkanAvailable = false;
|
vulkanAvailable = false;
|
||||||
return;
|
return;
|
||||||
@ -1801,16 +1801,13 @@ public:
|
|||||||
void setupTextureImage()
|
void setupTextureImage()
|
||||||
{
|
{
|
||||||
// Load the image data
|
// Load the image data
|
||||||
const auto maybeImageData = sf::Image::createFromFile("resources/logo.png");
|
sf::Image imageData;
|
||||||
|
if (!imageData.loadFromFile("resources/logo.png"))
|
||||||
if (!maybeImageData)
|
|
||||||
{
|
{
|
||||||
vulkanAvailable = false;
|
vulkanAvailable = false;
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
const auto& imageData = *maybeImageData;
|
|
||||||
|
|
||||||
// Create a staging buffer to transfer the data with
|
// Create a staging buffer to transfer the data with
|
||||||
const VkDeviceSize imageSize = imageData.getSize().x * imageData.getSize().y * 4;
|
const VkDeviceSize imageSize = imageData.getSize().x * imageData.getSize().y * 4;
|
||||||
|
|
||||||
|
@ -111,10 +111,10 @@ int main()
|
|||||||
sf::RenderWindow sfmlView2(view2);
|
sf::RenderWindow sfmlView2(view2);
|
||||||
|
|
||||||
// Load some textures to display
|
// Load some textures to display
|
||||||
const auto texture1 = sf::Texture::createFromFile("resources/image1.jpg").value();
|
const sf::Texture texture1("resources/image1.jpg");
|
||||||
const auto texture2 = sf::Texture::createFromFile("resources/image2.jpg").value();
|
const sf::Texture texture2("resources/image2.jpg");
|
||||||
sf::Sprite sprite1(texture1);
|
sf::Sprite sprite1(texture1);
|
||||||
sf::Sprite sprite2(texture2);
|
sf::Sprite sprite2(texture2);
|
||||||
sprite1.setOrigin(sf::Vector2f(texture1.getSize()) / 2.f);
|
sprite1.setOrigin(sf::Vector2f(texture1.getSize()) / 2.f);
|
||||||
sprite1.setPosition(sprite1.getOrigin());
|
sprite1.setPosition(sprite1.getOrigin());
|
||||||
|
|
||||||
|
@ -33,7 +33,6 @@
|
|||||||
|
|
||||||
#include <filesystem>
|
#include <filesystem>
|
||||||
#include <memory>
|
#include <memory>
|
||||||
#include <optional>
|
|
||||||
#include <vector>
|
#include <vector>
|
||||||
|
|
||||||
#include <cstddef>
|
#include <cstddef>
|
||||||
@ -61,6 +60,51 @@ public:
|
|||||||
////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////
|
||||||
InputSoundFile() = default;
|
InputSoundFile() = default;
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////
|
||||||
|
/// \brief Construct a sound file from the disk for reading
|
||||||
|
///
|
||||||
|
/// The supported audio formats are: WAV (PCM only), OGG/Vorbis, FLAC, MP3.
|
||||||
|
/// The supported sample sizes for FLAC and WAV are 8, 16, 24 and 32 bit.
|
||||||
|
///
|
||||||
|
/// Because of minimp3_ex limitation, for MP3 files with big (>16kb) APEv2 tag,
|
||||||
|
/// it may not be properly removed, tag data will be treated as MP3 data
|
||||||
|
/// and there is a low chance of garbage decoded at the end of file.
|
||||||
|
/// See also: https://github.com/lieff/minimp3
|
||||||
|
///
|
||||||
|
/// \param filename Path of the sound file to load
|
||||||
|
///
|
||||||
|
/// \throws std::runtime_error if opening the file was unsuccessful
|
||||||
|
///
|
||||||
|
////////////////////////////////////////////////////////////
|
||||||
|
InputSoundFile(const std::filesystem::path& filename);
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////
|
||||||
|
/// \brief Construct a sound file in memory for reading
|
||||||
|
///
|
||||||
|
/// The supported audio formats are: WAV (PCM only), OGG/Vorbis, FLAC.
|
||||||
|
/// The supported sample sizes for FLAC and WAV are 8, 16, 24 and 32 bit.
|
||||||
|
///
|
||||||
|
/// \param data Pointer to the file data in memory
|
||||||
|
/// \param sizeInBytes Size of the data to load, in bytes
|
||||||
|
///
|
||||||
|
/// \throws std::runtime_error if opening the file was unsuccessful
|
||||||
|
///
|
||||||
|
////////////////////////////////////////////////////////////
|
||||||
|
InputSoundFile(const void* data, std::size_t sizeInBytes);
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////
|
||||||
|
/// \brief Construct a sound file from a custom stream for reading
|
||||||
|
///
|
||||||
|
/// The supported audio formats are: WAV (PCM only), OGG/Vorbis, FLAC.
|
||||||
|
/// The supported sample sizes for FLAC and WAV are 8, 16, 24 and 32 bit.
|
||||||
|
///
|
||||||
|
/// \param stream Source stream to read from
|
||||||
|
///
|
||||||
|
/// \throws std::runtime_error if opening the file was unsuccessful
|
||||||
|
///
|
||||||
|
////////////////////////////////////////////////////////////
|
||||||
|
InputSoundFile(InputStream& stream);
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////
|
||||||
/// \brief Open a sound file from the disk for reading
|
/// \brief Open a sound file from the disk for reading
|
||||||
///
|
///
|
||||||
@ -106,51 +150,6 @@ public:
|
|||||||
////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////
|
||||||
[[nodiscard]] bool openFromStream(InputStream& stream);
|
[[nodiscard]] bool openFromStream(InputStream& stream);
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////
|
|
||||||
/// \brief Create a sound file from the disk for reading
|
|
||||||
///
|
|
||||||
/// The supported audio formats are: WAV (PCM only), OGG/Vorbis, FLAC, MP3.
|
|
||||||
/// The supported sample sizes for FLAC and WAV are 8, 16, 24 and 32 bit.
|
|
||||||
///
|
|
||||||
/// Because of minimp3_ex limitation, for MP3 files with big (>16kb) APEv2 tag,
|
|
||||||
/// it may not be properly removed, tag data will be treated as MP3 data
|
|
||||||
/// and there is a low chance of garbage decoded at the end of file.
|
|
||||||
/// See also: https://github.com/lieff/minimp3
|
|
||||||
///
|
|
||||||
/// \param filename Path of the sound file to load
|
|
||||||
///
|
|
||||||
/// \return Input sound file if the file was successfully opened, otherwise `std::nullopt`
|
|
||||||
///
|
|
||||||
////////////////////////////////////////////////////////////
|
|
||||||
[[nodiscard]] static std::optional<InputSoundFile> createFromFile(const std::filesystem::path& filename);
|
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////
|
|
||||||
/// \brief Create a sound file in memory for reading
|
|
||||||
///
|
|
||||||
/// The supported audio formats are: WAV (PCM only), OGG/Vorbis, FLAC.
|
|
||||||
/// The supported sample sizes for FLAC and WAV are 8, 16, 24 and 32 bit.
|
|
||||||
///
|
|
||||||
/// \param data Pointer to the file data in memory
|
|
||||||
/// \param sizeInBytes Size of the data to load, in bytes
|
|
||||||
///
|
|
||||||
/// \return Input sound file if the file was successfully opened, otherwise `std::nullopt`
|
|
||||||
///
|
|
||||||
////////////////////////////////////////////////////////////
|
|
||||||
[[nodiscard]] static std::optional<InputSoundFile> createFromMemory(const void* data, std::size_t sizeInBytes);
|
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////
|
|
||||||
/// \brief Create a sound file from a custom stream for reading
|
|
||||||
///
|
|
||||||
/// The supported audio formats are: WAV (PCM only), OGG/Vorbis, FLAC.
|
|
||||||
/// The supported sample sizes for FLAC and WAV are 8, 16, 24 and 32 bit.
|
|
||||||
///
|
|
||||||
/// \param stream Source stream to read from
|
|
||||||
///
|
|
||||||
/// \return Input sound file if the file was successfully opened, otherwise `std::nullopt`
|
|
||||||
///
|
|
||||||
////////////////////////////////////////////////////////////
|
|
||||||
[[nodiscard]] static std::optional<InputSoundFile> createFromStream(InputStream& stream);
|
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////
|
||||||
/// \brief Get the total number of audio samples in the file
|
/// \brief Get the total number of audio samples in the file
|
||||||
///
|
///
|
||||||
@ -311,7 +310,7 @@ private:
|
|||||||
/// Usage example:
|
/// Usage example:
|
||||||
/// \code
|
/// \code
|
||||||
/// // Open a sound file
|
/// // Open a sound file
|
||||||
/// auto file = sf::InputSoundFile::createFromFile("music.ogg").value();
|
/// sf::InputSoundFile file("music.ogg");
|
||||||
///
|
///
|
||||||
/// // Print the sound attributes
|
/// // Print the sound attributes
|
||||||
/// std::cout << "duration: " << file.getDuration().asSeconds() << '\n'
|
/// std::cout << "duration: " << file.getDuration().asSeconds() << '\n'
|
||||||
|
@ -74,6 +74,71 @@ public:
|
|||||||
////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////
|
||||||
Music();
|
Music();
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////
|
||||||
|
/// \brief Construct a music from an audio file
|
||||||
|
///
|
||||||
|
/// This function doesn't start playing the music (call play()
|
||||||
|
/// to do so).
|
||||||
|
/// See the documentation of sf::InputSoundFile for the list
|
||||||
|
/// of supported formats.
|
||||||
|
///
|
||||||
|
/// \warning Since the music is not loaded at once but rather
|
||||||
|
/// streamed continuously, the file must remain accessible until
|
||||||
|
/// the sf::Music object loads a new music or is destroyed.
|
||||||
|
///
|
||||||
|
/// \param filename Path of the music file to open
|
||||||
|
///
|
||||||
|
/// \throws std::runtime_error if loading was unsuccessful
|
||||||
|
///
|
||||||
|
/// \see openFromMemory, openFromStream
|
||||||
|
///
|
||||||
|
////////////////////////////////////////////////////////////
|
||||||
|
Music(const std::filesystem::path& filename);
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////
|
||||||
|
/// \brief Construct a music from an audio file in memory
|
||||||
|
///
|
||||||
|
/// This function doesn't start playing the music (call play()
|
||||||
|
/// to do so).
|
||||||
|
/// See the documentation of sf::InputSoundFile for the list
|
||||||
|
/// of supported formats.
|
||||||
|
///
|
||||||
|
/// \warning Since the music is not loaded at once but rather streamed
|
||||||
|
/// continuously, the \a data buffer must remain accessible until
|
||||||
|
/// the sf::Music object loads a new music or is destroyed. That is,
|
||||||
|
/// you can't deallocate the buffer right after calling this function.
|
||||||
|
///
|
||||||
|
/// \param data Pointer to the file data in memory
|
||||||
|
/// \param sizeInBytes Size of the data to load, in bytes
|
||||||
|
///
|
||||||
|
/// \throws std::runtime_error if loading was unsuccessful
|
||||||
|
///
|
||||||
|
/// \see openFromFile, openFromStream
|
||||||
|
///
|
||||||
|
////////////////////////////////////////////////////////////
|
||||||
|
Music(const void* data, std::size_t sizeInBytes);
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////
|
||||||
|
/// \brief Construct a music from an audio file in a custom stream
|
||||||
|
///
|
||||||
|
/// This function doesn't start playing the music (call play()
|
||||||
|
/// to do so).
|
||||||
|
/// See the documentation of sf::InputSoundFile for the list
|
||||||
|
/// of supported formats.
|
||||||
|
///
|
||||||
|
/// \warning Since the music is not loaded at once but rather
|
||||||
|
/// streamed continuously, the \a stream must remain accessible
|
||||||
|
/// until the sf::Music object loads a new music or is destroyed.
|
||||||
|
///
|
||||||
|
/// \param stream Source stream to read from
|
||||||
|
///
|
||||||
|
/// \throws std::runtime_error if loading was unsuccessful
|
||||||
|
///
|
||||||
|
/// \see openFromFile, openFromMemory
|
||||||
|
///
|
||||||
|
////////////////////////////////////////////////////////////
|
||||||
|
Music(InputStream& stream);
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////
|
||||||
/// \brief Destructor
|
/// \brief Destructor
|
||||||
///
|
///
|
||||||
@ -157,71 +222,6 @@ public:
|
|||||||
////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////
|
||||||
[[nodiscard]] bool openFromStream(InputStream& stream);
|
[[nodiscard]] bool openFromStream(InputStream& stream);
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////
|
|
||||||
/// \brief Create a music from an audio file
|
|
||||||
///
|
|
||||||
/// This function doesn't start playing the music (call play()
|
|
||||||
/// to do so).
|
|
||||||
/// See the documentation of sf::InputSoundFile for the list
|
|
||||||
/// of supported formats.
|
|
||||||
///
|
|
||||||
/// \warning Since the music is not loaded at once but rather
|
|
||||||
/// streamed continuously, the file must remain accessible until
|
|
||||||
/// the sf::Music object loads a new music or is destroyed.
|
|
||||||
///
|
|
||||||
/// \param filename Path of the music file to open
|
|
||||||
///
|
|
||||||
/// \return Music if loading succeeded, `std::nullopt` if it failed
|
|
||||||
///
|
|
||||||
/// \see createFromMemory, createFromStream
|
|
||||||
///
|
|
||||||
////////////////////////////////////////////////////////////
|
|
||||||
[[nodiscard]] static std::optional<Music> createFromFile(const std::filesystem::path& filename);
|
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////
|
|
||||||
/// \brief Create a music from an audio file in memory
|
|
||||||
///
|
|
||||||
/// This function doesn't start playing the music (call play()
|
|
||||||
/// to do so).
|
|
||||||
/// See the documentation of sf::InputSoundFile for the list
|
|
||||||
/// of supported formats.
|
|
||||||
///
|
|
||||||
/// \warning Since the music is not loaded at once but rather streamed
|
|
||||||
/// continuously, the \a data buffer must remain accessible until
|
|
||||||
/// the sf::Music object loads a new music or is destroyed. That is,
|
|
||||||
/// you can't deallocate the buffer right after calling this function.
|
|
||||||
///
|
|
||||||
/// \param data Pointer to the file data in memory
|
|
||||||
/// \param sizeInBytes Size of the data to load, in bytes
|
|
||||||
///
|
|
||||||
/// \return Music if loading succeeded, `std::nullopt` if it failed
|
|
||||||
///
|
|
||||||
/// \see createFromFile, createFromStream
|
|
||||||
///
|
|
||||||
////////////////////////////////////////////////////////////
|
|
||||||
[[nodiscard]] static std::optional<Music> createFromMemory(const void* data, std::size_t sizeInBytes);
|
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////
|
|
||||||
/// \brief Create a music from an audio file in a custom stream
|
|
||||||
///
|
|
||||||
/// This function doesn't start playing the music (call play()
|
|
||||||
/// to do so).
|
|
||||||
/// See the documentation of sf::InputSoundFile for the list
|
|
||||||
/// of supported formats.
|
|
||||||
///
|
|
||||||
/// \warning Since the music is not loaded at once but rather
|
|
||||||
/// streamed continuously, the \a stream must remain accessible
|
|
||||||
/// until the sf::Music object loads a new music or is destroyed.
|
|
||||||
///
|
|
||||||
/// \param stream Source stream to read from
|
|
||||||
///
|
|
||||||
/// \return Music if loading succeeded, `std::nullopt` if it failed
|
|
||||||
///
|
|
||||||
/// \see createFromFile, createFromMemory
|
|
||||||
///
|
|
||||||
////////////////////////////////////////////////////////////
|
|
||||||
[[nodiscard]] static std::optional<Music> createFromStream(InputStream& stream);
|
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////
|
||||||
/// \brief Get the total duration of the music
|
/// \brief Get the total duration of the music
|
||||||
///
|
///
|
||||||
@ -360,7 +360,7 @@ private:
|
|||||||
/// Usage example:
|
/// Usage example:
|
||||||
/// \code
|
/// \code
|
||||||
/// // Open a music from an audio file
|
/// // Open a music from an audio file
|
||||||
/// auto music = sf::Music::createFromFile("music.ogg").value();
|
/// sf::Music music("music.ogg");
|
||||||
///
|
///
|
||||||
/// // Change some parameters
|
/// // Change some parameters
|
||||||
/// music.setPosition({0, 1, 10}); // change its 3D position
|
/// music.setPosition({0, 1, 10}); // change its 3D position
|
||||||
|
@ -34,7 +34,6 @@
|
|||||||
|
|
||||||
#include <filesystem>
|
#include <filesystem>
|
||||||
#include <memory>
|
#include <memory>
|
||||||
#include <optional>
|
|
||||||
#include <vector>
|
#include <vector>
|
||||||
|
|
||||||
#include <cstdint>
|
#include <cstdint>
|
||||||
@ -58,6 +57,24 @@ public:
|
|||||||
////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////
|
||||||
OutputSoundFile() = default;
|
OutputSoundFile() = default;
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////
|
||||||
|
/// \brief Construct the sound file from the disk for writing
|
||||||
|
///
|
||||||
|
/// The supported audio formats are: WAV, OGG/Vorbis, FLAC.
|
||||||
|
///
|
||||||
|
/// \param filename Path of the sound file to write
|
||||||
|
/// \param sampleRate Sample rate of the sound
|
||||||
|
/// \param channelCount Number of channels in the sound
|
||||||
|
/// \param channelMap Map of position in sample frame to sound channel
|
||||||
|
///
|
||||||
|
/// \throws std::runtime_error if the file could not be opened successfully
|
||||||
|
///
|
||||||
|
////////////////////////////////////////////////////////////
|
||||||
|
OutputSoundFile(const std::filesystem::path& filename,
|
||||||
|
unsigned int sampleRate,
|
||||||
|
unsigned int channelCount,
|
||||||
|
const std::vector<SoundChannel>& channelMap);
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////
|
||||||
/// \brief Open the sound file from the disk for writing
|
/// \brief Open the sound file from the disk for writing
|
||||||
///
|
///
|
||||||
@ -76,25 +93,6 @@ public:
|
|||||||
unsigned int channelCount,
|
unsigned int channelCount,
|
||||||
const std::vector<SoundChannel>& channelMap);
|
const std::vector<SoundChannel>& channelMap);
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////
|
|
||||||
/// \brief Create the sound file from the disk for writing
|
|
||||||
///
|
|
||||||
/// The supported audio formats are: WAV, OGG/Vorbis, FLAC.
|
|
||||||
///
|
|
||||||
/// \param filename Path of the sound file to write
|
|
||||||
/// \param sampleRate Sample rate of the sound
|
|
||||||
/// \param channelCount Number of channels in the sound
|
|
||||||
/// \param channelMap Map of position in sample frame to sound channel
|
|
||||||
///
|
|
||||||
/// \return Output sound file if the file was successfully opened
|
|
||||||
///
|
|
||||||
////////////////////////////////////////////////////////////
|
|
||||||
[[nodiscard]] static std::optional<OutputSoundFile> createFromFile(
|
|
||||||
const std::filesystem::path& filename,
|
|
||||||
unsigned int sampleRate,
|
|
||||||
unsigned int channelCount,
|
|
||||||
const std::vector<SoundChannel>& channelMap);
|
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////
|
||||||
/// \brief Write audio samples to the file
|
/// \brief Write audio samples to the file
|
||||||
///
|
///
|
||||||
@ -132,7 +130,7 @@ private:
|
|||||||
/// Usage example:
|
/// Usage example:
|
||||||
/// \code
|
/// \code
|
||||||
/// // Create a sound file, ogg/vorbis format, 44100 Hz, stereo
|
/// // Create a sound file, ogg/vorbis format, 44100 Hz, stereo
|
||||||
/// auto file = sf::OutputSoundFile::createFromFile("music.ogg", 44100, 2).value();
|
/// sf::OutputSoundFile file("music.ogg", 44100, 2, {sf::SoundChannel::FrontLeft, sf::SoundChannel::FrontRight});
|
||||||
///
|
///
|
||||||
/// while (...)
|
/// while (...)
|
||||||
/// {
|
/// {
|
||||||
|
@ -274,7 +274,7 @@ private:
|
|||||||
///
|
///
|
||||||
/// Usage example:
|
/// Usage example:
|
||||||
/// \code
|
/// \code
|
||||||
/// const auto buffer = sf::SoundBuffer::createFromFile("sound.wav").value();
|
/// const sf::SoundBuffer buffer("sound.wav");
|
||||||
/// sf::Sound sound(buffer);
|
/// sf::Sound sound(buffer);
|
||||||
/// sound.play();
|
/// sound.play();
|
||||||
/// \endcode
|
/// \endcode
|
||||||
|
@ -34,7 +34,6 @@
|
|||||||
#include <SFML/System/Time.hpp>
|
#include <SFML/System/Time.hpp>
|
||||||
|
|
||||||
#include <filesystem>
|
#include <filesystem>
|
||||||
#include <optional>
|
|
||||||
#include <unordered_set>
|
#include <unordered_set>
|
||||||
#include <vector>
|
#include <vector>
|
||||||
|
|
||||||
@ -72,6 +71,74 @@ public:
|
|||||||
////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////
|
||||||
SoundBuffer(const SoundBuffer& copy);
|
SoundBuffer(const SoundBuffer& copy);
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////
|
||||||
|
/// \brief Construct the sound buffer from a file
|
||||||
|
///
|
||||||
|
/// See the documentation of sf::InputSoundFile for the list
|
||||||
|
/// of supported formats.
|
||||||
|
///
|
||||||
|
/// \param filename Path of the sound file to load
|
||||||
|
///
|
||||||
|
/// \throws std::runtime_error if loading was unsuccessful
|
||||||
|
///
|
||||||
|
/// \see loadFromMemory, loadFromStream, loadFromSamples, saveToFile
|
||||||
|
///
|
||||||
|
////////////////////////////////////////////////////////////
|
||||||
|
SoundBuffer(const std::filesystem::path& filename);
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////
|
||||||
|
/// \brief Construct the sound buffer from a file in memory
|
||||||
|
///
|
||||||
|
/// See the documentation of sf::InputSoundFile for the list
|
||||||
|
/// of supported formats.
|
||||||
|
///
|
||||||
|
/// \param data Pointer to the file data in memory
|
||||||
|
/// \param sizeInBytes Size of the data to load, in bytes
|
||||||
|
///
|
||||||
|
/// \throws std::runtime_error if loading was unsuccessful
|
||||||
|
///
|
||||||
|
/// \see loadFromFile, loadFromStream, loadFromSamples
|
||||||
|
///
|
||||||
|
////////////////////////////////////////////////////////////
|
||||||
|
SoundBuffer(const void* data, std::size_t sizeInBytes);
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////
|
||||||
|
/// \brief Construct the sound buffer from a custom stream
|
||||||
|
///
|
||||||
|
/// See the documentation of sf::InputSoundFile for the list
|
||||||
|
/// of supported formats.
|
||||||
|
///
|
||||||
|
/// \param stream Source stream to read from
|
||||||
|
///
|
||||||
|
/// \throws std::runtime_error if loading was unsuccessful
|
||||||
|
///
|
||||||
|
/// \see loadFromFile, loadFromMemory, loadFromSamples
|
||||||
|
///
|
||||||
|
////////////////////////////////////////////////////////////
|
||||||
|
SoundBuffer(InputStream& stream);
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////
|
||||||
|
/// \brief Construct the sound buffer from an array of audio samples
|
||||||
|
///
|
||||||
|
/// The assumed format of the audio samples is 16 bit signed integer.
|
||||||
|
///
|
||||||
|
/// \param samples Pointer to the array of samples in memory
|
||||||
|
/// \param sampleCount Number of samples in the array
|
||||||
|
/// \param channelCount Number of channels (1 = mono, 2 = stereo, ...)
|
||||||
|
/// \param sampleRate Sample rate (number of samples to play per second)
|
||||||
|
/// \param channelMap Map of position in sample frame to sound channel
|
||||||
|
///
|
||||||
|
/// \throws std::runtime_error if loading was unsuccessful
|
||||||
|
///
|
||||||
|
/// \see loadFromFile, loadFromMemory, saveToFile
|
||||||
|
///
|
||||||
|
////////////////////////////////////////////////////////////
|
||||||
|
SoundBuffer(const std::int16_t* samples,
|
||||||
|
std::uint64_t sampleCount,
|
||||||
|
unsigned int channelCount,
|
||||||
|
unsigned int sampleRate,
|
||||||
|
const std::vector<SoundChannel>& channelMap);
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////
|
||||||
/// \brief Destructor
|
/// \brief Destructor
|
||||||
///
|
///
|
||||||
@ -146,75 +213,6 @@ public:
|
|||||||
unsigned int sampleRate,
|
unsigned int sampleRate,
|
||||||
const std::vector<SoundChannel>& channelMap);
|
const std::vector<SoundChannel>& channelMap);
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////
|
|
||||||
/// \brief Create the sound buffer from a file
|
|
||||||
///
|
|
||||||
/// See the documentation of sf::InputSoundFile for the list
|
|
||||||
/// of supported formats.
|
|
||||||
///
|
|
||||||
/// \param filename Path of the sound file to load
|
|
||||||
///
|
|
||||||
/// \return Sound buffer if loading succeeded, `std::nullopt` if it failed
|
|
||||||
///
|
|
||||||
/// \see createFromMemory, createFromStream, createFromSamples, saveToFile
|
|
||||||
///
|
|
||||||
////////////////////////////////////////////////////////////
|
|
||||||
[[nodiscard]] static std::optional<SoundBuffer> createFromFile(const std::filesystem::path& filename);
|
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////
|
|
||||||
/// \brief Create the sound buffer from a file in memory
|
|
||||||
///
|
|
||||||
/// See the documentation of sf::InputSoundFile for the list
|
|
||||||
/// of supported formats.
|
|
||||||
///
|
|
||||||
/// \param data Pointer to the file data in memory
|
|
||||||
/// \param sizeInBytes Size of the data to load, in bytes
|
|
||||||
///
|
|
||||||
/// \return Sound buffer if loading succeeded, `std::nullopt` if it failed
|
|
||||||
///
|
|
||||||
/// \see createFromFile, createFromStream, createFromSamples
|
|
||||||
///
|
|
||||||
////////////////////////////////////////////////////////////
|
|
||||||
[[nodiscard]] static std::optional<SoundBuffer> createFromMemory(const void* data, std::size_t sizeInBytes);
|
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////
|
|
||||||
/// \brief Create the sound buffer from a custom stream
|
|
||||||
///
|
|
||||||
/// See the documentation of sf::InputSoundFile for the list
|
|
||||||
/// of supported formats.
|
|
||||||
///
|
|
||||||
/// \param stream Source stream to read from
|
|
||||||
///
|
|
||||||
/// \return Sound buffer if loading succeeded, `std::nullopt` if it failed
|
|
||||||
///
|
|
||||||
/// \see createFromFile, createFromMemory, createFromSamples
|
|
||||||
///
|
|
||||||
////////////////////////////////////////////////////////////
|
|
||||||
[[nodiscard]] static std::optional<SoundBuffer> createFromStream(InputStream& stream);
|
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////
|
|
||||||
/// \brief Create the sound buffer from an array of audio samples
|
|
||||||
///
|
|
||||||
/// The assumed format of the audio samples is 16 bits signed integer.
|
|
||||||
///
|
|
||||||
/// \param samples Pointer to the array of samples in memory
|
|
||||||
/// \param sampleCount Number of samples in the array
|
|
||||||
/// \param channelCount Number of channels (1 = mono, 2 = stereo, ...)
|
|
||||||
/// \param sampleRate Sample rate (number of samples to play per second)
|
|
||||||
/// \param channelMap Map of position in sample frame to sound channel
|
|
||||||
///
|
|
||||||
/// \return Sound buffer if loading succeeded, `std::nullopt` if it failed
|
|
||||||
///
|
|
||||||
/// \see createFromFile, createFromMemory, saveToFile
|
|
||||||
///
|
|
||||||
////////////////////////////////////////////////////////////
|
|
||||||
[[nodiscard]] static std::optional<SoundBuffer> createFromSamples(
|
|
||||||
const std::int16_t* samples,
|
|
||||||
std::uint64_t sampleCount,
|
|
||||||
unsigned int channelCount,
|
|
||||||
unsigned int sampleRate,
|
|
||||||
const std::vector<SoundChannel>& channelMap);
|
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////
|
||||||
/// \brief Save the sound buffer to an audio file
|
/// \brief Save the sound buffer to an audio file
|
||||||
///
|
///
|
||||||
@ -225,8 +223,6 @@ public:
|
|||||||
///
|
///
|
||||||
/// \return True if saving succeeded, false if it failed
|
/// \return True if saving succeeded, false if it failed
|
||||||
///
|
///
|
||||||
/// \see createFromFile, createFromMemory, createFromSamples
|
|
||||||
///
|
|
||||||
////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////
|
||||||
[[nodiscard]] bool saveToFile(const std::filesystem::path& filename) const;
|
[[nodiscard]] bool saveToFile(const std::filesystem::path& filename) const;
|
||||||
|
|
||||||
@ -389,8 +385,7 @@ private:
|
|||||||
/// are like texture pixels, and a sf::SoundBuffer is similar to
|
/// are like texture pixels, and a sf::SoundBuffer is similar to
|
||||||
/// a sf::Texture.
|
/// a sf::Texture.
|
||||||
///
|
///
|
||||||
/// A sound buffer can be loaded from a file (see createFromFile()
|
/// A sound buffer can be loaded from a file, from memory, from
|
||||||
/// for the complete list of supported formats), from memory, from
|
|
||||||
/// a custom stream (see sf::InputStream) or directly from an array
|
/// a custom stream (see sf::InputStream) or directly from an array
|
||||||
/// of samples. It can also be saved back to a file.
|
/// of samples. It can also be saved back to a file.
|
||||||
///
|
///
|
||||||
@ -415,7 +410,7 @@ private:
|
|||||||
/// Usage example:
|
/// Usage example:
|
||||||
/// \code
|
/// \code
|
||||||
/// // Load a new sound buffer from a file
|
/// // Load a new sound buffer from a file
|
||||||
/// const auto buffer = sf::SoundBuffer::createFromFile("sound.wav").value();
|
/// const sf::SoundBuffer buffer("sound.wav");
|
||||||
///
|
///
|
||||||
/// // Create a sound source bound to the buffer
|
/// // Create a sound source bound to the buffer
|
||||||
/// sf::Sound sound1(buffer);
|
/// sf::Sound sound1(buffer);
|
||||||
|
@ -37,7 +37,6 @@
|
|||||||
|
|
||||||
#include <filesystem>
|
#include <filesystem>
|
||||||
#include <memory>
|
#include <memory>
|
||||||
#include <optional>
|
|
||||||
#include <string>
|
#include <string>
|
||||||
#include <unordered_map>
|
#include <unordered_map>
|
||||||
#include <vector>
|
#include <vector>
|
||||||
@ -81,6 +80,71 @@ public:
|
|||||||
////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////
|
||||||
Font() = default;
|
Font() = default;
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////
|
||||||
|
/// \brief Construct the font from a file
|
||||||
|
///
|
||||||
|
/// The supported font formats are: TrueType, Type 1, CFF,
|
||||||
|
/// OpenType, SFNT, X11 PCF, Windows FNT, BDF, PFR and Type 42.
|
||||||
|
/// Note that this function knows nothing about the standard
|
||||||
|
/// fonts installed on the user's system, thus you can't
|
||||||
|
/// load them directly.
|
||||||
|
///
|
||||||
|
/// \warning SFML cannot preload all the font data in this
|
||||||
|
/// function, so the file has to remain accessible until
|
||||||
|
/// the sf::Font object opens a new font or is destroyed.
|
||||||
|
///
|
||||||
|
/// \param filename Path of the font file to open
|
||||||
|
///
|
||||||
|
/// \throws std::runtime_error if opening was unsuccessful
|
||||||
|
///
|
||||||
|
/// \see openFromFile, openFromMemory, openFromStream
|
||||||
|
///
|
||||||
|
////////////////////////////////////////////////////////////
|
||||||
|
Font(const std::filesystem::path& filename);
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////
|
||||||
|
/// \brief Construct the font from a file in memory
|
||||||
|
///
|
||||||
|
/// The supported font formats are: TrueType, Type 1, CFF,
|
||||||
|
/// OpenType, SFNT, X11 PCF, Windows FNT, BDF, PFR and Type 42.
|
||||||
|
///
|
||||||
|
/// \warning SFML cannot preload all the font data in this
|
||||||
|
/// function, so the buffer pointed by \a data has to remain
|
||||||
|
/// valid until the sf::Font object opens a new font or
|
||||||
|
/// is destroyed.
|
||||||
|
///
|
||||||
|
/// \param data Pointer to the file data in memory
|
||||||
|
/// \param sizeInBytes Size of the data to load, in bytes
|
||||||
|
///
|
||||||
|
/// \throws std::runtime_error if loading was unsuccessful
|
||||||
|
///
|
||||||
|
/// \see openFromFile, openFromMemory, openFromStream
|
||||||
|
///
|
||||||
|
////////////////////////////////////////////////////////////
|
||||||
|
Font(const void* data, std::size_t sizeInBytes);
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////
|
||||||
|
/// \brief Construct the font from a custom stream
|
||||||
|
///
|
||||||
|
/// The supported font formats are: TrueType, Type 1, CFF,
|
||||||
|
/// OpenType, SFNT, X11 PCF, Windows FNT, BDF, PFR and Type 42.
|
||||||
|
/// Warning: SFML cannot preload all the font data in this
|
||||||
|
/// function, so the contents of \a stream have to remain
|
||||||
|
/// valid as long as the font is used.
|
||||||
|
///
|
||||||
|
/// \warning SFML cannot preload all the font data in this
|
||||||
|
/// function, so the stream has to remain accessible until
|
||||||
|
/// the sf::Font object opens a new font or is destroyed.
|
||||||
|
///
|
||||||
|
/// \param stream Source stream to read from
|
||||||
|
///
|
||||||
|
/// \throws std::runtime_error if loading was unsuccessful
|
||||||
|
///
|
||||||
|
/// \see openFromFile, openFromMemory, openFromStream
|
||||||
|
///
|
||||||
|
////////////////////////////////////////////////////////////
|
||||||
|
Font(InputStream& stream);
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////
|
||||||
/// \brief Open the font from a file
|
/// \brief Open the font from a file
|
||||||
///
|
///
|
||||||
@ -92,11 +156,11 @@ public:
|
|||||||
///
|
///
|
||||||
/// \warning SFML cannot preload all the font data in this
|
/// \warning SFML cannot preload all the font data in this
|
||||||
/// function, so the file has to remain accessible until
|
/// function, so the file has to remain accessible until
|
||||||
/// the sf::Font object loads a new font or is destroyed.
|
/// the sf::Font object opens a new font or is destroyed.
|
||||||
///
|
///
|
||||||
/// \param filename Path of the font file to load
|
/// \param filename Path of the font file to load
|
||||||
///
|
///
|
||||||
/// \return True if loading succeeded, false if it failed
|
/// \return True if opening succeeded, false if it failed
|
||||||
///
|
///
|
||||||
/// \see openFromMemory, openFromStream
|
/// \see openFromMemory, openFromStream
|
||||||
///
|
///
|
||||||
@ -111,13 +175,13 @@ public:
|
|||||||
///
|
///
|
||||||
/// \warning SFML cannot preload all the font data in this
|
/// \warning SFML cannot preload all the font data in this
|
||||||
/// function, so the buffer pointed by \a data has to remain
|
/// function, so the buffer pointed by \a data has to remain
|
||||||
/// valid until the sf::Font object loads a new font or
|
/// valid until the sf::Font object opens a new font or
|
||||||
/// is destroyed.
|
/// is destroyed.
|
||||||
///
|
///
|
||||||
/// \param data Pointer to the file data in memory
|
/// \param data Pointer to the file data in memory
|
||||||
/// \param sizeInBytes Size of the data to load, in bytes
|
/// \param sizeInBytes Size of the data to load, in bytes
|
||||||
///
|
///
|
||||||
/// \return True if loading succeeded, false if it failed
|
/// \return True if opening succeeded, false if it failed
|
||||||
///
|
///
|
||||||
/// \see openFromFile, openFromStream
|
/// \see openFromFile, openFromStream
|
||||||
///
|
///
|
||||||
@ -129,84 +193,20 @@ public:
|
|||||||
///
|
///
|
||||||
/// The supported font formats are: TrueType, Type 1, CFF,
|
/// The supported font formats are: TrueType, Type 1, CFF,
|
||||||
/// OpenType, SFNT, X11 PCF, Windows FNT, BDF, PFR and Type 42.
|
/// OpenType, SFNT, X11 PCF, Windows FNT, BDF, PFR and Type 42.
|
||||||
/// Warning: SFML cannot preload all the font data in this
|
|
||||||
/// function, so the contents of \a stream have to remain
|
|
||||||
/// valid as long as the font is used.
|
|
||||||
///
|
///
|
||||||
/// \warning SFML cannot preload all the font data in this
|
/// \warning SFML cannot preload all the font data in this
|
||||||
/// function, so the stream has to remain accessible until
|
/// function, so the stream has to remain accessible until
|
||||||
/// the sf::Font object loads a new font or is destroyed.
|
/// the sf::Font object opens a new font or is destroyed.
|
||||||
///
|
///
|
||||||
/// \param stream Source stream to read from
|
/// \param stream Source stream to read from
|
||||||
///
|
///
|
||||||
/// \return True if loading succeeded, false if it failed
|
/// \return True if opening succeeded, false if it failed
|
||||||
///
|
///
|
||||||
/// \see openFromFile, openFromMemory
|
/// \see openFromFile, openFromMemory
|
||||||
///
|
///
|
||||||
////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////
|
||||||
[[nodiscard]] bool openFromStream(InputStream& stream);
|
[[nodiscard]] bool openFromStream(InputStream& stream);
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////
|
|
||||||
/// \brief Create the font from a file
|
|
||||||
///
|
|
||||||
/// The supported font formats are: TrueType, Type 1, CFF,
|
|
||||||
/// OpenType, SFNT, X11 PCF, Windows FNT, BDF, PFR and Type 42.
|
|
||||||
/// Note that this function knows nothing about the standard
|
|
||||||
/// fonts installed on the user's system, thus you can't
|
|
||||||
/// load them directly.
|
|
||||||
///
|
|
||||||
/// \warning SFML cannot preload all the font data in this
|
|
||||||
/// function, so the file has to remain accessible until
|
|
||||||
/// the sf::Font object is destroyed.
|
|
||||||
///
|
|
||||||
/// \param filename Path of the font file to load
|
|
||||||
///
|
|
||||||
/// \return Font if opening succeeded, `std::nullopt` if it failed
|
|
||||||
///
|
|
||||||
/// \see createFromMemory, createFromStream
|
|
||||||
///
|
|
||||||
////////////////////////////////////////////////////////////
|
|
||||||
[[nodiscard]] static std::optional<Font> createFromFile(const std::filesystem::path& filename);
|
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////
|
|
||||||
/// \brief Create the font from a file in memory
|
|
||||||
///
|
|
||||||
/// The supported font formats are: TrueType, Type 1, CFF,
|
|
||||||
/// OpenType, SFNT, X11 PCF, Windows FNT, BDF, PFR and Type 42.
|
|
||||||
///
|
|
||||||
/// \warning SFML cannot preload all the font data in this
|
|
||||||
/// function, so the buffer pointed by \a data has to remain
|
|
||||||
/// valid until the sf::Font object is destroyed.
|
|
||||||
///
|
|
||||||
/// \param data Pointer to the file data in memory
|
|
||||||
/// \param sizeInBytes Size of the data to load, in bytes
|
|
||||||
///
|
|
||||||
/// \return Font if opening succeeded, `std::nullopt` if it failed
|
|
||||||
///
|
|
||||||
/// \see createFromFile, createFromStream
|
|
||||||
///
|
|
||||||
////////////////////////////////////////////////////////////
|
|
||||||
[[nodiscard]] static std::optional<Font> createFromMemory(const void* data, std::size_t sizeInBytes);
|
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////
|
|
||||||
/// \brief Create the font from a custom stream
|
|
||||||
///
|
|
||||||
/// The supported font formats are: TrueType, Type 1, CFF,
|
|
||||||
/// OpenType, SFNT, X11 PCF, Windows FNT, BDF, PFR and Type 42.
|
|
||||||
///
|
|
||||||
/// \warning SFML cannot preload all the font data in this
|
|
||||||
/// function, so the stream has to remain accessible until
|
|
||||||
/// the sf::Font object is destroyed.
|
|
||||||
///
|
|
||||||
/// \param stream Source stream to read from
|
|
||||||
///
|
|
||||||
/// \return Font if opening succeeded, `std::nullopt` if it failed
|
|
||||||
///
|
|
||||||
/// \see createFromFile, createFromMemory
|
|
||||||
///
|
|
||||||
////////////////////////////////////////////////////////////
|
|
||||||
[[nodiscard]] static std::optional<Font> createFromStream(InputStream& stream);
|
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////
|
||||||
/// \brief Get the font information
|
/// \brief Get the font information
|
||||||
///
|
///
|
||||||
@ -474,7 +474,7 @@ private:
|
|||||||
///
|
///
|
||||||
/// Fonts can be opened from a file, from memory or from a custom
|
/// Fonts can be opened from a file, from memory or from a custom
|
||||||
/// stream, and supports the most common types of fonts. See
|
/// stream, and supports the most common types of fonts. See
|
||||||
/// the createFromFile function for the complete list of supported formats.
|
/// the openFromFile function for the complete list of supported formats.
|
||||||
///
|
///
|
||||||
/// Once it is opened, a sf::Font instance provides three
|
/// Once it is opened, a sf::Font instance provides three
|
||||||
/// types of information about the font:
|
/// types of information about the font:
|
||||||
@ -505,7 +505,7 @@ private:
|
|||||||
/// Usage example:
|
/// Usage example:
|
||||||
/// \code
|
/// \code
|
||||||
/// // Open a new font
|
/// // Open a new font
|
||||||
/// const auto font = sf::Font::createFromFile("arial.ttf").value();
|
/// const sf::Font font("arial.ttf");
|
||||||
///
|
///
|
||||||
/// // Create a text which uses our font
|
/// // Create a text which uses our font
|
||||||
/// sf::Text text1(font);
|
/// sf::Text text1(font);
|
||||||
|
@ -59,6 +59,8 @@ public:
|
|||||||
///
|
///
|
||||||
/// Constructs an image with width 0 and height 0.
|
/// Constructs an image with width 0 and height 0.
|
||||||
///
|
///
|
||||||
|
/// \see resize
|
||||||
|
///
|
||||||
////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////
|
||||||
Image() = default;
|
Image() = default;
|
||||||
|
|
||||||
@ -85,6 +87,55 @@ public:
|
|||||||
////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////
|
||||||
Image(Vector2u size, const std::uint8_t* pixels);
|
Image(Vector2u size, const std::uint8_t* pixels);
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////
|
||||||
|
/// \brief Construct the image from a file on disk
|
||||||
|
///
|
||||||
|
/// The supported image formats are bmp, png, tga, jpg, gif,
|
||||||
|
/// psd, hdr, pic and pnm. Some format options are not supported,
|
||||||
|
/// like jpeg with arithmetic coding or ASCII pnm.
|
||||||
|
///
|
||||||
|
/// \param filename Path of the image file to load
|
||||||
|
///
|
||||||
|
/// \throws std::runtime_error if loading was unsuccessful
|
||||||
|
///
|
||||||
|
/// \see loadFromFile, loadFromMemory, loadFromStream
|
||||||
|
///
|
||||||
|
////////////////////////////////////////////////////////////
|
||||||
|
explicit Image(const std::filesystem::path& filename);
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////
|
||||||
|
/// \brief Construct the image from a file in memory
|
||||||
|
///
|
||||||
|
/// The supported image formats are bmp, png, tga, jpg, gif,
|
||||||
|
/// psd, hdr, pic and pnm. Some format options are not supported,
|
||||||
|
/// like jpeg with arithmetic coding or ASCII pnm.
|
||||||
|
///
|
||||||
|
/// \param data Pointer to the file data in memory
|
||||||
|
/// \param size Size of the data to load, in bytes
|
||||||
|
///
|
||||||
|
/// \throws std::runtime_error if loading was unsuccessful
|
||||||
|
///
|
||||||
|
/// \see loadFromFile, loadFromMemory, loadFromStream
|
||||||
|
///
|
||||||
|
////////////////////////////////////////////////////////////
|
||||||
|
Image(const void* data, std::size_t size);
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////
|
||||||
|
/// \brief Construct the image from a custom stream
|
||||||
|
///
|
||||||
|
/// The supported image formats are bmp, png, tga, jpg, gif,
|
||||||
|
/// psd, hdr, pic and pnm. Some format options are not supported,
|
||||||
|
/// like jpeg with arithmetic coding or ASCII pnm.
|
||||||
|
///
|
||||||
|
/// \param stream Source stream to read from
|
||||||
|
///
|
||||||
|
/// \throws std::runtime_error if loading was unsuccessful
|
||||||
|
///
|
||||||
|
/// \see loadFromFile, loadFromMemory, loadFromStream
|
||||||
|
///
|
||||||
|
////////////////////////////////////////////////////////////
|
||||||
|
explicit Image(InputStream& stream);
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////
|
||||||
/// \brief Resize the image and fill it with a unique color
|
/// \brief Resize the image and fill it with a unique color
|
||||||
///
|
///
|
||||||
@ -138,7 +189,7 @@ public:
|
|||||||
///
|
///
|
||||||
/// \return True if loading was successful
|
/// \return True if loading was successful
|
||||||
///
|
///
|
||||||
/// \see loadFromFile, loadFromStream
|
/// \see loadFromFile, loadFromStream, saveToMemory
|
||||||
///
|
///
|
||||||
////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////
|
||||||
[[nodiscard]] bool loadFromMemory(const void* data, std::size_t size);
|
[[nodiscard]] bool loadFromMemory(const void* data, std::size_t size);
|
||||||
@ -160,58 +211,6 @@ public:
|
|||||||
////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////
|
||||||
[[nodiscard]] bool loadFromStream(InputStream& stream);
|
[[nodiscard]] bool loadFromStream(InputStream& stream);
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////
|
|
||||||
/// \brief Load the image from a file on disk
|
|
||||||
///
|
|
||||||
/// The supported image formats are bmp, png, tga, jpg, gif,
|
|
||||||
/// psd, hdr, pic and pnm. Some format options are not supported,
|
|
||||||
/// like jpeg with arithmetic coding or ASCII pnm.
|
|
||||||
/// If this function fails, the image is left unchanged.
|
|
||||||
///
|
|
||||||
/// \param filename Path of the image file to load
|
|
||||||
///
|
|
||||||
/// \return Image if loading was successful, `std::nullopt` otherwise
|
|
||||||
///
|
|
||||||
/// \see createFromMemory, createFromStream, saveToFile
|
|
||||||
///
|
|
||||||
////////////////////////////////////////////////////////////
|
|
||||||
[[nodiscard]] static std::optional<Image> createFromFile(const std::filesystem::path& filename);
|
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////
|
|
||||||
/// \brief Load the image from a file in memory
|
|
||||||
///
|
|
||||||
/// The supported image formats are bmp, png, tga, jpg, gif,
|
|
||||||
/// psd, hdr, pic and pnm. Some format options are not supported,
|
|
||||||
/// like jpeg with arithmetic coding or ASCII pnm.
|
|
||||||
/// If this function fails, the image is left unchanged.
|
|
||||||
///
|
|
||||||
/// \param data Pointer to the file data in memory
|
|
||||||
/// \param size Size of the data to load, in bytes
|
|
||||||
///
|
|
||||||
/// \return Image if loading was successful, `std::nullopt` otherwise
|
|
||||||
///
|
|
||||||
/// \see createFromFile, createFromStream
|
|
||||||
///
|
|
||||||
////////////////////////////////////////////////////////////
|
|
||||||
[[nodiscard]] static std::optional<Image> createFromMemory(const void* data, std::size_t size);
|
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////
|
|
||||||
/// \brief Load the image from a custom stream
|
|
||||||
///
|
|
||||||
/// The supported image formats are bmp, png, tga, jpg, gif,
|
|
||||||
/// psd, hdr, pic and pnm. Some format options are not supported,
|
|
||||||
/// like jpeg with arithmetic coding or ASCII pnm.
|
|
||||||
/// If this function fails, the image is left unchanged.
|
|
||||||
///
|
|
||||||
/// \param stream Source stream to read from
|
|
||||||
///
|
|
||||||
/// \return Image if loading was successful, `std::nullopt` otherwise
|
|
||||||
///
|
|
||||||
/// \see createFromFile, createFromMemory
|
|
||||||
///
|
|
||||||
////////////////////////////////////////////////////////////
|
|
||||||
[[nodiscard]] static std::optional<Image> createFromStream(InputStream& stream);
|
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////
|
||||||
/// \brief Save the image to a file on disk
|
/// \brief Save the image to a file on disk
|
||||||
///
|
///
|
||||||
@ -224,7 +223,7 @@ public:
|
|||||||
///
|
///
|
||||||
/// \return True if saving was successful
|
/// \return True if saving was successful
|
||||||
///
|
///
|
||||||
/// \see create, createFromFile, createFromMemory
|
/// \see saveToMemory, loadFromFile
|
||||||
///
|
///
|
||||||
////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////
|
||||||
[[nodiscard]] bool saveToFile(const std::filesystem::path& filename) const;
|
[[nodiscard]] bool saveToFile(const std::filesystem::path& filename) const;
|
||||||
@ -242,7 +241,7 @@ public:
|
|||||||
/// \return Buffer with encoded data if saving was successful,
|
/// \return Buffer with encoded data if saving was successful,
|
||||||
/// otherwise std::nullopt
|
/// otherwise std::nullopt
|
||||||
///
|
///
|
||||||
/// \see create, createFromFile, createFromMemory, saveToFile
|
/// \see saveToFile, loadFromMemory
|
||||||
///
|
///
|
||||||
////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////
|
||||||
[[nodiscard]] std::optional<std::vector<std::uint8_t>> saveToMemory(std::string_view format) const;
|
[[nodiscard]] std::optional<std::vector<std::uint8_t>> saveToMemory(std::string_view format) const;
|
||||||
@ -386,7 +385,7 @@ private:
|
|||||||
/// channels -- just like a sf::Color.
|
/// channels -- just like a sf::Color.
|
||||||
/// All the functions that return an array of pixels follow
|
/// All the functions that return an array of pixels follow
|
||||||
/// this rule, and all parameters that you pass to sf::Image
|
/// this rule, and all parameters that you pass to sf::Image
|
||||||
/// functions (such as createFromMemory) must use this
|
/// functions (such as loadFromMemory) must use this
|
||||||
/// representation as well.
|
/// representation as well.
|
||||||
///
|
///
|
||||||
/// A sf::Image can be copied, but it is a heavy resource and
|
/// A sf::Image can be copied, but it is a heavy resource and
|
||||||
@ -396,7 +395,7 @@ private:
|
|||||||
/// Usage example:
|
/// Usage example:
|
||||||
/// \code
|
/// \code
|
||||||
/// // Load an image file from a file
|
/// // Load an image file from a file
|
||||||
/// const auto background = sf::Image::createFromFile("background.jpg").value();
|
/// const sf::Image background("background.jpg");
|
||||||
///
|
///
|
||||||
/// // Create a 20x20 image filled with black color
|
/// // Create a 20x20 image filled with black color
|
||||||
/// sf::Image image({20, 20}, sf::Color::Black);
|
/// sf::Image image({20, 20}, sf::Color::Black);
|
||||||
|
@ -37,7 +37,6 @@
|
|||||||
#include <SFML/System/Vector2.hpp>
|
#include <SFML/System/Vector2.hpp>
|
||||||
|
|
||||||
#include <memory>
|
#include <memory>
|
||||||
#include <optional>
|
|
||||||
|
|
||||||
|
|
||||||
namespace sf
|
namespace sf
|
||||||
@ -64,6 +63,25 @@ public:
|
|||||||
////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////
|
||||||
RenderTexture();
|
RenderTexture();
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////
|
||||||
|
/// \brief Construct a render-texture
|
||||||
|
///
|
||||||
|
/// The last parameter, \a settings, is useful if you want to enable
|
||||||
|
/// multi-sampling or use the render-texture for OpenGL rendering that
|
||||||
|
/// requires a depth or stencil buffer. Otherwise it is unnecessary, and
|
||||||
|
/// you should leave this parameter at its default value.
|
||||||
|
///
|
||||||
|
/// After creation, the contents of the render-texture are undefined.
|
||||||
|
/// Call `RenderTexture::clear` first to ensure a single color fill.
|
||||||
|
///
|
||||||
|
/// \param size Width and height of the render-texture
|
||||||
|
/// \param settings Additional settings for the underlying OpenGL texture and context
|
||||||
|
///
|
||||||
|
/// \throws std::runtime_error if creation was unsuccessful
|
||||||
|
///
|
||||||
|
////////////////////////////////////////////////////////////
|
||||||
|
RenderTexture(Vector2u size, const ContextSettings& settings = {});
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////
|
||||||
/// \brief Destructor
|
/// \brief Destructor
|
||||||
///
|
///
|
||||||
@ -108,29 +126,10 @@ public:
|
|||||||
/// \param size Width and height of the render-texture
|
/// \param size Width and height of the render-texture
|
||||||
/// \param settings Additional settings for the underlying OpenGL texture and context
|
/// \param settings Additional settings for the underlying OpenGL texture and context
|
||||||
///
|
///
|
||||||
/// \return True if resizing has been successful
|
/// \return True if resizing has been successful, false if it failed
|
||||||
///
|
///
|
||||||
////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////
|
||||||
[[nodiscard]] bool resize(Vector2u size, const ContextSettings& settings = ContextSettings());
|
[[nodiscard]] bool resize(Vector2u size, const ContextSettings& settings = {});
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////
|
|
||||||
/// \brief Create the render-texture
|
|
||||||
///
|
|
||||||
/// The last parameter, \a settings, is useful if you want to enable
|
|
||||||
/// multi-sampling or use the render-texture for OpenGL rendering that
|
|
||||||
/// requires a depth or stencil buffer. Otherwise it is unnecessary, and
|
|
||||||
/// you should leave this parameter at its default value.
|
|
||||||
///
|
|
||||||
/// After creation, the contents of the render-texture are undefined.
|
|
||||||
/// Call `RenderTexture::clear` first to ensure a single color fill.
|
|
||||||
///
|
|
||||||
/// \param size Width and height of the render-texture
|
|
||||||
/// \param settings Additional settings for the underlying OpenGL texture and context
|
|
||||||
///
|
|
||||||
/// \return Render texture if creation has been successful, otherwise `std::nullopt`
|
|
||||||
///
|
|
||||||
////////////////////////////////////////////////////////////
|
|
||||||
[[nodiscard]] static std::optional<RenderTexture> create(Vector2u size, const ContextSettings& settings = {});
|
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////
|
||||||
/// \brief Get the maximum anti-aliasing level supported by the system
|
/// \brief Get the maximum anti-aliasing level supported by the system
|
||||||
@ -302,7 +301,7 @@ private:
|
|||||||
/// sf::RenderWindow window(sf::VideoMode({800, 600}), "SFML window");
|
/// sf::RenderWindow window(sf::VideoMode({800, 600}), "SFML window");
|
||||||
///
|
///
|
||||||
/// // Create a new render-texture
|
/// // Create a new render-texture
|
||||||
/// auto texture = sf::RenderTexture::create({500, 500}).value();
|
/// sf::RenderTexture texture({500, 500});
|
||||||
///
|
///
|
||||||
/// // The main loop
|
/// // The main loop
|
||||||
/// while (window.isOpen())
|
/// while (window.isOpen())
|
||||||
|
@ -87,7 +87,7 @@ public:
|
|||||||
const String& title,
|
const String& title,
|
||||||
std::uint32_t style = Style::Default,
|
std::uint32_t style = Style::Default,
|
||||||
State state = State::Windowed,
|
State state = State::Windowed,
|
||||||
const ContextSettings& settings = ContextSettings());
|
const ContextSettings& settings = {});
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////
|
||||||
/// \brief Construct a new window
|
/// \brief Construct a new window
|
||||||
@ -106,7 +106,7 @@ public:
|
|||||||
/// \param settings Additional settings for the underlying OpenGL context
|
/// \param settings Additional settings for the underlying OpenGL context
|
||||||
///
|
///
|
||||||
////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////
|
||||||
RenderWindow(VideoMode mode, const String& title, State state, const ContextSettings& settings = ContextSettings());
|
RenderWindow(VideoMode mode, const String& title, State state, const ContextSettings& settings = {});
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////
|
||||||
/// \brief Construct the window from an existing control
|
/// \brief Construct the window from an existing control
|
||||||
@ -124,7 +124,7 @@ public:
|
|||||||
/// \param settings Additional settings for the underlying OpenGL context
|
/// \param settings Additional settings for the underlying OpenGL context
|
||||||
///
|
///
|
||||||
////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////
|
||||||
explicit RenderWindow(WindowHandle handle, const ContextSettings& settings = ContextSettings());
|
explicit RenderWindow(WindowHandle handle, const ContextSettings& settings = {});
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////
|
||||||
/// \brief Get the size of the rendering region of the window
|
/// \brief Get the size of the rendering region of the window
|
||||||
@ -266,9 +266,9 @@ private:
|
|||||||
/// sf::RenderWindow window(sf::VideoMode({800, 600}), "SFML OpenGL");
|
/// sf::RenderWindow window(sf::VideoMode({800, 600}), "SFML OpenGL");
|
||||||
///
|
///
|
||||||
/// // Create a sprite and a text to display
|
/// // Create a sprite and a text to display
|
||||||
/// const auto texture = sf::Texture::createFromFile("circle.png").value();
|
/// const sf::Texture texture("circle.png");
|
||||||
/// sf::Sprite sprite(texture);
|
/// sf::Sprite sprite(texture);
|
||||||
/// const auto font = sf::Font::createFromFile("arial.ttf").value();
|
/// const sf::Font font("arial.ttf");
|
||||||
/// sf::Text text(font);
|
/// sf::Text text(font);
|
||||||
/// ...
|
/// ...
|
||||||
///
|
///
|
||||||
|
@ -34,7 +34,6 @@
|
|||||||
#include <SFML/Window/GlResource.hpp>
|
#include <SFML/Window/GlResource.hpp>
|
||||||
|
|
||||||
#include <filesystem>
|
#include <filesystem>
|
||||||
#include <optional>
|
|
||||||
#include <string>
|
#include <string>
|
||||||
#include <string_view>
|
#include <string_view>
|
||||||
#include <unordered_map>
|
#include <unordered_map>
|
||||||
@ -126,6 +125,198 @@ public:
|
|||||||
////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////
|
||||||
Shader& operator=(Shader&& right) noexcept;
|
Shader& operator=(Shader&& right) noexcept;
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////
|
||||||
|
/// \brief Construct from a shader file
|
||||||
|
///
|
||||||
|
/// This constructor loads a single shader, vertex, geometry or
|
||||||
|
/// fragment, identified by the second argument.
|
||||||
|
/// The source must be a text file containing 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 filename Path of the vertex, geometry or fragment shader file to load
|
||||||
|
/// \param type Type of shader (vertex, geometry or fragment)
|
||||||
|
///
|
||||||
|
/// \throws std::runtime_error if loading was unsuccessful
|
||||||
|
///
|
||||||
|
/// \see loadFromFile, loadFromMemory, loadFromStream
|
||||||
|
///
|
||||||
|
////////////////////////////////////////////////////////////
|
||||||
|
Shader(const std::filesystem::path& filename, Type type);
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////
|
||||||
|
/// \brief Construct from vertex and fragment shader files
|
||||||
|
///
|
||||||
|
/// This constructor 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
|
||||||
|
///
|
||||||
|
/// \throws std::runtime_error if loading was unsuccessful
|
||||||
|
///
|
||||||
|
/// \see loadFromFile, loadFromMemory, loadFromStream
|
||||||
|
///
|
||||||
|
////////////////////////////////////////////////////////////
|
||||||
|
Shader(const std::filesystem::path& vertexShaderFilename, const std::filesystem::path& fragmentShaderFilename);
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////
|
||||||
|
/// \brief Construct from vertex, geometry and fragment shader files
|
||||||
|
///
|
||||||
|
/// This constructor loads the vertex, geometry and 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 geometryShaderFilename Path of the geometry shader file to load
|
||||||
|
/// \param fragmentShaderFilename Path of the fragment shader file to load
|
||||||
|
///
|
||||||
|
/// \throws std::runtime_error if loading was unsuccessful
|
||||||
|
///
|
||||||
|
/// \see loadFromFile, loadFromMemory, loadFromStream
|
||||||
|
///
|
||||||
|
////////////////////////////////////////////////////////////
|
||||||
|
Shader(const std::filesystem::path& vertexShaderFilename,
|
||||||
|
const std::filesystem::path& geometryShaderFilename,
|
||||||
|
const std::filesystem::path& fragmentShaderFilename);
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////
|
||||||
|
/// \brief Construct from shader in memory
|
||||||
|
///
|
||||||
|
/// This constructor loads a single shader, vertex, geometry
|
||||||
|
/// 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, geometry or fragment)
|
||||||
|
///
|
||||||
|
/// \throws std::runtime_error if loading was unsuccessful
|
||||||
|
///
|
||||||
|
/// \see loadFromFile, loadFromMemory, loadFromStream
|
||||||
|
///
|
||||||
|
////////////////////////////////////////////////////////////
|
||||||
|
Shader(std::string_view shader, Type type);
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////
|
||||||
|
/// \brief Construct from vertex and fragment shaders in memory
|
||||||
|
///
|
||||||
|
/// This constructor 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
|
||||||
|
///
|
||||||
|
/// \throws std::runtime_error if loading was unsuccessful
|
||||||
|
///
|
||||||
|
/// \see loadFromFile, loadFromMemory, loadFromStream
|
||||||
|
///
|
||||||
|
////////////////////////////////////////////////////////////
|
||||||
|
Shader(std::string_view vertexShader, std::string_view fragmentShader);
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////
|
||||||
|
/// \brief Construct from vertex, geometry and fragment shaders in memory
|
||||||
|
///
|
||||||
|
/// This constructor loads the vertex, geometry and 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 geometryShader String containing the source code of the geometry shader
|
||||||
|
/// \param fragmentShader String containing the source code of the fragment shader
|
||||||
|
///
|
||||||
|
/// \throws std::runtime_error if loading was unsuccessful
|
||||||
|
///
|
||||||
|
/// \see loadFromFile, loadFromMemory, loadFromStream
|
||||||
|
///
|
||||||
|
////////////////////////////////////////////////////////////
|
||||||
|
Shader(std::string_view vertexShader, std::string_view geometryShader, std::string_view fragmentShader);
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////
|
||||||
|
/// \brief Construct from a shader stream
|
||||||
|
///
|
||||||
|
/// This constructor loads a single shader, vertex, geometry
|
||||||
|
/// 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, geometry or fragment)
|
||||||
|
///
|
||||||
|
/// \throws std::runtime_error if loading was unsuccessful
|
||||||
|
///
|
||||||
|
/// \see loadFromFile, loadFromMemory, loadFromStream
|
||||||
|
///
|
||||||
|
////////////////////////////////////////////////////////////
|
||||||
|
Shader(InputStream& stream, Type type);
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////
|
||||||
|
/// \brief Construct from vertex and fragment shader streams
|
||||||
|
///
|
||||||
|
/// This constructor 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
|
||||||
|
///
|
||||||
|
/// \throws std::runtime_error if loading was unsuccessful
|
||||||
|
///
|
||||||
|
/// \see loadFromFile, loadFromMemory, loadFromStream
|
||||||
|
///
|
||||||
|
////////////////////////////////////////////////////////////
|
||||||
|
Shader(InputStream& vertexShaderStream, InputStream& fragmentShaderStream);
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////
|
||||||
|
/// \brief Construct from vertex, geometry and fragment shader streams
|
||||||
|
///
|
||||||
|
/// This constructor loads the vertex, geometry and 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 geometryShaderStream Source stream to read the geometry shader from
|
||||||
|
/// \param fragmentShaderStream Source stream to read the fragment shader from
|
||||||
|
///
|
||||||
|
/// \throws std::runtime_error if loading was unsuccessful
|
||||||
|
///
|
||||||
|
/// \see loadFromFile, loadFromMemory, loadFromStream
|
||||||
|
///
|
||||||
|
////////////////////////////////////////////////////////////
|
||||||
|
Shader(InputStream& vertexShaderStream, InputStream& geometryShaderStream, InputStream& fragmentShaderStream);
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////
|
||||||
/// \brief Load the vertex, geometry or fragment shader from a file
|
/// \brief Load the vertex, geometry or fragment shader from a file
|
||||||
///
|
///
|
||||||
@ -323,204 +514,6 @@ public:
|
|||||||
InputStream& geometryShaderStream,
|
InputStream& geometryShaderStream,
|
||||||
InputStream& fragmentShaderStream);
|
InputStream& fragmentShaderStream);
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////
|
|
||||||
/// \brief Load the vertex, geometry or fragment shader from a file
|
|
||||||
///
|
|
||||||
/// This function loads a single shader, vertex, geometry or
|
|
||||||
/// fragment, identified by the second argument.
|
|
||||||
/// The source must be a text file containing 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 filename Path of the vertex, geometry or fragment shader file to load
|
|
||||||
/// \param type Type of shader (vertex, geometry or fragment)
|
|
||||||
///
|
|
||||||
/// \return Shader if loading succeeded, `std::nullopt` if it failed
|
|
||||||
///
|
|
||||||
/// \see createFromMemory, createFromStream
|
|
||||||
///
|
|
||||||
////////////////////////////////////////////////////////////
|
|
||||||
[[nodiscard]] static std::optional<Shader> createFromFile(const std::filesystem::path& filename, Type type);
|
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////
|
|
||||||
/// \brief Load both the vertex and fragment shaders from files
|
|
||||||
///
|
|
||||||
/// 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 Shader if loading succeeded, `std::nullopt` if it failed
|
|
||||||
///
|
|
||||||
/// \see createFromMemory, createFromStream
|
|
||||||
///
|
|
||||||
////////////////////////////////////////////////////////////
|
|
||||||
[[nodiscard]] static std::optional<Shader> createFromFile(const std::filesystem::path& vertexShaderFilename,
|
|
||||||
const std::filesystem::path& fragmentShaderFilename);
|
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////
|
|
||||||
/// \brief Load the vertex, geometry and fragment shaders from files
|
|
||||||
///
|
|
||||||
/// This function loads the vertex, geometry and 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 geometryShaderFilename Path of the geometry shader file to load
|
|
||||||
/// \param fragmentShaderFilename Path of the fragment shader file to load
|
|
||||||
///
|
|
||||||
/// \return Shader if loading succeeded, `std::nullopt` if it failed
|
|
||||||
///
|
|
||||||
/// \see createFromMemory, createFromStream
|
|
||||||
///
|
|
||||||
////////////////////////////////////////////////////////////
|
|
||||||
[[nodiscard]] static std::optional<Shader> createFromFile(const std::filesystem::path& vertexShaderFilename,
|
|
||||||
const std::filesystem::path& geometryShaderFilename,
|
|
||||||
const std::filesystem::path& fragmentShaderFilename);
|
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////
|
|
||||||
/// \brief Load the vertex, geometry or fragment shader from a source code in memory
|
|
||||||
///
|
|
||||||
/// This function loads a single shader, vertex, geometry
|
|
||||||
/// 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, geometry or fragment)
|
|
||||||
///
|
|
||||||
/// \return Shader if loading succeeded, `std::nullopt` if it failed
|
|
||||||
///
|
|
||||||
/// \see createFromFile, createFromStream
|
|
||||||
///
|
|
||||||
////////////////////////////////////////////////////////////
|
|
||||||
[[nodiscard]] static std::optional<Shader> createFromMemory(std::string_view shader, Type type);
|
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////
|
|
||||||
/// \brief Load both the vertex and fragment shaders from source codes in memory
|
|
||||||
///
|
|
||||||
/// 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 Shader if loading succeeded, `std::nullopt` if it failed
|
|
||||||
///
|
|
||||||
/// \see createFromFile, createFromStream
|
|
||||||
///
|
|
||||||
////////////////////////////////////////////////////////////
|
|
||||||
[[nodiscard]] static std::optional<Shader> createFromMemory(std::string_view vertexShader, std::string_view fragmentShader);
|
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////
|
|
||||||
/// \brief Load the vertex, geometry and fragment shaders from source codes in memory
|
|
||||||
///
|
|
||||||
/// This function loads the vertex, geometry and 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 geometryShader String containing the source code of the geometry shader
|
|
||||||
/// \param fragmentShader String containing the source code of the fragment shader
|
|
||||||
///
|
|
||||||
/// \return Shader if loading succeeded, `std::nullopt` if it failed
|
|
||||||
///
|
|
||||||
/// \see createFromFile, createFromStream
|
|
||||||
///
|
|
||||||
////////////////////////////////////////////////////////////
|
|
||||||
[[nodiscard]] static std::optional<Shader> createFromMemory(std::string_view vertexShader,
|
|
||||||
std::string_view geometryShader,
|
|
||||||
std::string_view fragmentShader);
|
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////
|
|
||||||
/// \brief Load the vertex, geometry or fragment shader from a custom stream
|
|
||||||
///
|
|
||||||
/// This function loads a single shader, vertex, geometry
|
|
||||||
/// 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, geometry or fragment)
|
|
||||||
///
|
|
||||||
/// \return Shader if loading succeeded, `std::nullopt` if it failed
|
|
||||||
///
|
|
||||||
/// \see createFromFile, createFromMemory
|
|
||||||
///
|
|
||||||
////////////////////////////////////////////////////////////
|
|
||||||
[[nodiscard]] static std::optional<Shader> createFromStream(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 Shader if loading succeeded, `std::nullopt` if it failed
|
|
||||||
///
|
|
||||||
/// \see createFromFile, createFromMemory
|
|
||||||
///
|
|
||||||
////////////////////////////////////////////////////////////
|
|
||||||
[[nodiscard]] static std::optional<Shader> createFromStream(InputStream& vertexShaderStream,
|
|
||||||
InputStream& fragmentShaderStream);
|
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////
|
|
||||||
/// \brief Load the vertex, geometry and fragment shaders from custom streams
|
|
||||||
///
|
|
||||||
/// This function loads the vertex, geometry and 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 geometryShaderStream Source stream to read the geometry shader from
|
|
||||||
/// \param fragmentShaderStream Source stream to read the fragment shader from
|
|
||||||
///
|
|
||||||
/// \return Shader if loading succeeded, `std::nullopt` if it failed
|
|
||||||
///
|
|
||||||
/// \see createFromFile, createFromMemory
|
|
||||||
///
|
|
||||||
////////////////////////////////////////////////////////////
|
|
||||||
[[nodiscard]] static std::optional<Shader> createFromStream(InputStream& vertexShaderStream,
|
|
||||||
InputStream& geometryShaderStream,
|
|
||||||
InputStream& fragmentShaderStream);
|
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////
|
||||||
/// \brief Specify value for \p float uniform
|
/// \brief Specify value for \p float uniform
|
||||||
///
|
///
|
||||||
|
@ -261,7 +261,7 @@ private:
|
|||||||
/// Usage example:
|
/// Usage example:
|
||||||
/// \code
|
/// \code
|
||||||
/// // Load a texture
|
/// // Load a texture
|
||||||
/// const auto texture = sf::Texture::createFromFile("texture.png").value();
|
/// const sf::Texture texture("texture.png");
|
||||||
///
|
///
|
||||||
/// // Create a sprite
|
/// // Create a sprite
|
||||||
/// sf::Sprite sprite(texture);
|
/// sf::Sprite sprite(texture);
|
||||||
|
@ -469,7 +469,7 @@ private:
|
|||||||
/// Usage example:
|
/// Usage example:
|
||||||
/// \code
|
/// \code
|
||||||
/// // Open a font
|
/// // Open a font
|
||||||
/// const auto font = sf::Font::createFromFile("arial.ttf").value();
|
/// const sf::Font font("arial.ttf");
|
||||||
///
|
///
|
||||||
/// // Create a text
|
/// // Create a text
|
||||||
/// sf::Text text(font, "hello");
|
/// sf::Text text(font, "hello");
|
||||||
|
@ -37,7 +37,6 @@
|
|||||||
#include <SFML/System/Vector2.hpp>
|
#include <SFML/System/Vector2.hpp>
|
||||||
|
|
||||||
#include <filesystem>
|
#include <filesystem>
|
||||||
#include <optional>
|
|
||||||
|
|
||||||
#include <cstddef>
|
#include <cstddef>
|
||||||
#include <cstdint>
|
#include <cstdint>
|
||||||
@ -61,6 +60,8 @@ public:
|
|||||||
///
|
///
|
||||||
/// Creates a texture with width 0 and height 0.
|
/// Creates a texture with width 0 and height 0.
|
||||||
///
|
///
|
||||||
|
/// \see resize
|
||||||
|
///
|
||||||
////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////
|
||||||
Texture();
|
Texture();
|
||||||
|
|
||||||
@ -96,6 +97,174 @@ public:
|
|||||||
////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////
|
||||||
Texture& operator=(Texture&&) noexcept;
|
Texture& operator=(Texture&&) noexcept;
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////
|
||||||
|
/// \brief Construct the texture from a file on disk
|
||||||
|
///
|
||||||
|
/// The maximum size for a texture depends on the graphics
|
||||||
|
/// driver and can be retrieved with the getMaximumSize function.
|
||||||
|
///
|
||||||
|
/// \param filename Path of the image file to load
|
||||||
|
/// \param sRgb True to enable sRGB conversion, false to disable it
|
||||||
|
///
|
||||||
|
/// \throws std::runtime_error if loading was unsuccessful
|
||||||
|
///
|
||||||
|
/// \see loadFromFile, loadFromMemory, loadFromStream, loadFromImage
|
||||||
|
///
|
||||||
|
////////////////////////////////////////////////////////////
|
||||||
|
explicit Texture(const std::filesystem::path& filename, bool sRgb = false);
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////
|
||||||
|
/// \brief Construct the texture from a sub-rectangle of a file on disk
|
||||||
|
///
|
||||||
|
/// The \a area argument can be used to load only a sub-rectangle
|
||||||
|
/// of the whole image. If you want the entire image then leave
|
||||||
|
/// the default value (which is an empty IntRect).
|
||||||
|
/// If the \a area rectangle crosses the bounds of the image, it
|
||||||
|
/// is adjusted to fit the image size.
|
||||||
|
///
|
||||||
|
/// The maximum size for a texture depends on the graphics
|
||||||
|
/// driver and can be retrieved with the getMaximumSize function.
|
||||||
|
///
|
||||||
|
/// \param filename Path of the image file to load
|
||||||
|
/// \param sRgb True to enable sRGB conversion, false to disable it
|
||||||
|
/// \param area Area of the image to load
|
||||||
|
///
|
||||||
|
/// \throws std::runtime_error if loading was unsuccessful
|
||||||
|
///
|
||||||
|
/// \see loadFromFile, loadFromMemory, loadFromStream, loadFromImage
|
||||||
|
///
|
||||||
|
////////////////////////////////////////////////////////////
|
||||||
|
Texture(const std::filesystem::path& filename, bool sRgb, const IntRect& area);
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////
|
||||||
|
/// \brief Construct the texture from a file in memory
|
||||||
|
///
|
||||||
|
/// The maximum size for a texture depends on the graphics
|
||||||
|
/// driver and can be retrieved with the getMaximumSize function.
|
||||||
|
///
|
||||||
|
/// \param data Pointer to the file data in memory
|
||||||
|
/// \param size Size of the data to load, in bytes
|
||||||
|
/// \param sRgb True to enable sRGB conversion, false to disable it
|
||||||
|
///
|
||||||
|
/// \throws std::runtime_error if loading was unsuccessful
|
||||||
|
///
|
||||||
|
/// \see loadFromFile, loadFromMemory, loadFromStream, loadFromImage
|
||||||
|
///
|
||||||
|
////////////////////////////////////////////////////////////
|
||||||
|
Texture(const void* data, std::size_t size, bool sRgb = false);
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////
|
||||||
|
/// \brief Construct the texture from a sub-rectangle of a file in memory
|
||||||
|
///
|
||||||
|
/// The \a area argument can be used to load only a sub-rectangle
|
||||||
|
/// of the whole image. If you want the entire image then leave
|
||||||
|
/// the default value (which is an empty IntRect).
|
||||||
|
/// If the \a area rectangle crosses the bounds of the image, it
|
||||||
|
/// is adjusted to fit the image size.
|
||||||
|
///
|
||||||
|
/// The maximum size for a texture depends on the graphics
|
||||||
|
/// driver and can be retrieved with the getMaximumSize function.
|
||||||
|
///
|
||||||
|
/// \param data Pointer to the file data in memory
|
||||||
|
/// \param size Size of the data to load, in bytes
|
||||||
|
/// \param sRgb True to enable sRGB conversion, false to disable it
|
||||||
|
/// \param area Area of the image to load
|
||||||
|
///
|
||||||
|
/// \throws std::runtime_error if loading was unsuccessful
|
||||||
|
///
|
||||||
|
/// \see loadFromFile, loadFromMemory, loadFromStream, loadFromImage
|
||||||
|
///
|
||||||
|
////////////////////////////////////////////////////////////
|
||||||
|
Texture(const void* data, std::size_t size, bool sRgb, const IntRect& area);
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////
|
||||||
|
/// \brief Construct the texture from a custom stream
|
||||||
|
///
|
||||||
|
/// The maximum size for a texture depends on the graphics
|
||||||
|
/// driver and can be retrieved with the getMaximumSize function.
|
||||||
|
///
|
||||||
|
/// \param stream Source stream to read from
|
||||||
|
/// \param sRgb True to enable sRGB conversion, false to disable it
|
||||||
|
///
|
||||||
|
/// \throws std::runtime_error if loading was unsuccessful
|
||||||
|
///
|
||||||
|
/// \see loadFromFile, loadFromMemory, loadFromStream, loadFromImage
|
||||||
|
///
|
||||||
|
////////////////////////////////////////////////////////////
|
||||||
|
explicit Texture(InputStream& stream, bool sRgb = false);
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////
|
||||||
|
/// \brief Construct the texture from a sub-rectangle of a custom stream
|
||||||
|
///
|
||||||
|
/// The \a area argument can be used to load only a sub-rectangle
|
||||||
|
/// of the whole image. If you want the entire image then leave
|
||||||
|
/// the default value (which is an empty IntRect).
|
||||||
|
/// If the \a area rectangle crosses the bounds of the image, it
|
||||||
|
/// is adjusted to fit the image size.
|
||||||
|
///
|
||||||
|
/// The maximum size for a texture depends on the graphics
|
||||||
|
/// driver and can be retrieved with the getMaximumSize function.
|
||||||
|
///
|
||||||
|
/// \param stream Source stream to read from
|
||||||
|
/// \param sRgb True to enable sRGB conversion, false to disable it
|
||||||
|
/// \param area Area of the image to load
|
||||||
|
///
|
||||||
|
/// \throws std::runtime_error if loading was unsuccessful
|
||||||
|
///
|
||||||
|
/// \see loadFromFile, loadFromMemory, loadFromStream, loadFromImage
|
||||||
|
///
|
||||||
|
////////////////////////////////////////////////////////////
|
||||||
|
Texture(InputStream& stream, bool sRgb, const IntRect& area);
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////
|
||||||
|
/// \brief Construct the texture from an image
|
||||||
|
///
|
||||||
|
/// The maximum size for a texture depends on the graphics
|
||||||
|
/// driver and can be retrieved with the getMaximumSize function.
|
||||||
|
///
|
||||||
|
/// \param image Image to load into the texture
|
||||||
|
/// \param sRgb True to enable sRGB conversion, false to disable it
|
||||||
|
///
|
||||||
|
/// \throws std::runtime_error if loading was unsuccessful
|
||||||
|
///
|
||||||
|
/// \see loadFromFile, loadFromMemory, loadFromStream, loadFromImage
|
||||||
|
///
|
||||||
|
////////////////////////////////////////////////////////////
|
||||||
|
explicit Texture(const Image& image, bool sRgb = false);
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////
|
||||||
|
/// \brief Construct the texture from a sub-rectangle of an image
|
||||||
|
///
|
||||||
|
/// The \a area argument is used to load only a sub-rectangle
|
||||||
|
/// of the whole image.
|
||||||
|
/// If the \a area rectangle crosses the bounds of the image, it
|
||||||
|
/// is adjusted to fit the image size.
|
||||||
|
///
|
||||||
|
/// The maximum size for a texture depends on the graphics
|
||||||
|
/// driver and can be retrieved with the getMaximumSize function.
|
||||||
|
///
|
||||||
|
/// \param image Image to load into the texture
|
||||||
|
/// \param sRgb True to enable sRGB conversion, false to disable it
|
||||||
|
/// \param area Area of the image to load
|
||||||
|
///
|
||||||
|
/// \throws std::runtime_error if loading was unsuccessful
|
||||||
|
///
|
||||||
|
/// \see loadFromFile, loadFromMemory, loadFromStream, loadFromImage
|
||||||
|
///
|
||||||
|
////////////////////////////////////////////////////////////
|
||||||
|
Texture(const Image& image, bool sRgb, const IntRect& area);
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////
|
||||||
|
/// \brief Construct the texture with a given size
|
||||||
|
///
|
||||||
|
/// \param size Width and height of the texture
|
||||||
|
/// \param sRgb True to enable sRGB conversion, false to disable it
|
||||||
|
///
|
||||||
|
/// \throws std::runtime_error if construction was unsuccessful
|
||||||
|
///
|
||||||
|
////////////////////////////////////////////////////////////
|
||||||
|
explicit Texture(Vector2u size, bool sRgb = false);
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////
|
||||||
/// \brief Resize the texture
|
/// \brief Resize the texture
|
||||||
///
|
///
|
||||||
@ -104,7 +273,7 @@ public:
|
|||||||
/// \param size Width and height of the texture
|
/// \param size Width and height of the texture
|
||||||
/// \param sRgb True to enable sRGB conversion, false to disable it
|
/// \param sRgb True to enable sRGB conversion, false to disable it
|
||||||
///
|
///
|
||||||
/// \return True if resizing was successful
|
/// \return True if resizing was successful, false if it failed
|
||||||
///
|
///
|
||||||
////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////
|
||||||
[[nodiscard]] bool resize(Vector2u size, bool sRgb = false);
|
[[nodiscard]] bool resize(Vector2u size, bool sRgb = false);
|
||||||
@ -112,15 +281,6 @@ public:
|
|||||||
////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////
|
||||||
/// \brief Load the texture from a file on disk
|
/// \brief Load the texture from a file on disk
|
||||||
///
|
///
|
||||||
/// This function is a shortcut for the following code:
|
|
||||||
/// \code
|
|
||||||
/// sf::Image image;
|
|
||||||
/// if (!image.loadFromFile(filename))
|
|
||||||
/// return false;
|
|
||||||
/// if (!texture.loadFromImage(image, area))
|
|
||||||
/// return false;
|
|
||||||
/// \endcode
|
|
||||||
///
|
|
||||||
/// The \a area argument can be used to load only a sub-rectangle
|
/// The \a area argument can be used to load only a sub-rectangle
|
||||||
/// of the whole image. If you want the entire image then leave
|
/// of the whole image. If you want the entire image then leave
|
||||||
/// the default value (which is an empty IntRect).
|
/// the default value (which is an empty IntRect).
|
||||||
@ -136,25 +296,16 @@ public:
|
|||||||
/// \param sRgb True to enable sRGB conversion, false to disable it
|
/// \param sRgb True to enable sRGB conversion, false to disable it
|
||||||
/// \param area Area of the image to load
|
/// \param area Area of the image to load
|
||||||
///
|
///
|
||||||
/// \return True if loading was successful
|
/// \return True if loading was successful, false if it failed
|
||||||
///
|
///
|
||||||
/// \see loadFromMemory, loadFromStream, loadFromImage
|
/// \see loadFromMemory, loadFromStream, loadFromImage
|
||||||
///
|
///
|
||||||
////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////
|
||||||
[[nodiscard]] bool loadFromFile(const std::filesystem::path& filename, bool sRgb = false, const IntRect& area = IntRect());
|
[[nodiscard]] bool loadFromFile(const std::filesystem::path& filename, bool sRgb = false, const IntRect& area = {});
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////
|
||||||
/// \brief Load the texture from a file in memory
|
/// \brief Load the texture from a file in memory
|
||||||
///
|
///
|
||||||
/// This function is a shortcut for the following code:
|
|
||||||
/// \code
|
|
||||||
/// sf::Image image;
|
|
||||||
/// if (!image.loadFromMemory(data, size))
|
|
||||||
/// return false;
|
|
||||||
/// if (!texture.loadFromImage(image, area))
|
|
||||||
/// return false;
|
|
||||||
/// \endcode
|
|
||||||
///
|
|
||||||
/// The \a area argument can be used to load only a sub-rectangle
|
/// The \a area argument can be used to load only a sub-rectangle
|
||||||
/// of the whole image. If you want the entire image then leave
|
/// of the whole image. If you want the entire image then leave
|
||||||
/// the default value (which is an empty IntRect).
|
/// the default value (which is an empty IntRect).
|
||||||
@ -171,25 +322,16 @@ public:
|
|||||||
/// \param sRgb True to enable sRGB conversion, false to disable it
|
/// \param sRgb True to enable sRGB conversion, false to disable it
|
||||||
/// \param area Area of the image to load
|
/// \param area Area of the image to load
|
||||||
///
|
///
|
||||||
/// \return True if loading was successful
|
/// \return True if loading was successful, false if it failed
|
||||||
///
|
///
|
||||||
/// \see loadFromFile, loadFromStream, loadFromImage
|
/// \see loadFromFile, loadFromStream, loadFromImage
|
||||||
///
|
///
|
||||||
////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////
|
||||||
[[nodiscard]] bool loadFromMemory(const void* data, std::size_t size, bool sRgb = false, const IntRect& area = IntRect());
|
[[nodiscard]] bool loadFromMemory(const void* data, std::size_t size, bool sRgb = false, const IntRect& area = {});
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////
|
||||||
/// \brief Load the texture from a custom stream
|
/// \brief Load the texture from a custom stream
|
||||||
///
|
///
|
||||||
/// This function is a shortcut for the following code:
|
|
||||||
/// \code
|
|
||||||
/// sf::Image image;
|
|
||||||
/// if (!image.loadFromStream(stream))
|
|
||||||
/// return false;
|
|
||||||
/// if (!texture.loadFromImage(image, area))
|
|
||||||
/// return false;
|
|
||||||
/// \endcode
|
|
||||||
///
|
|
||||||
/// The \a area argument can be used to load only a sub-rectangle
|
/// The \a area argument can be used to load only a sub-rectangle
|
||||||
/// of the whole image. If you want the entire image then leave
|
/// of the whole image. If you want the entire image then leave
|
||||||
/// the default value (which is an empty IntRect).
|
/// the default value (which is an empty IntRect).
|
||||||
@ -205,12 +347,12 @@ public:
|
|||||||
/// \param sRgb True to enable sRGB conversion, false to disable it
|
/// \param sRgb True to enable sRGB conversion, false to disable it
|
||||||
/// \param area Area of the image to load
|
/// \param area Area of the image to load
|
||||||
///
|
///
|
||||||
/// \return True if loading was successful
|
/// \return True if loading was successful, false if it failed
|
||||||
///
|
///
|
||||||
/// \see loadFromFile, loadFromMemory, loadFromImage
|
/// \see loadFromFile, loadFromMemory, loadFromImage
|
||||||
///
|
///
|
||||||
////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////
|
||||||
[[nodiscard]] bool loadFromStream(InputStream& stream, bool sRgb = false, const IntRect& area = IntRect());
|
[[nodiscard]] bool loadFromStream(InputStream& stream, bool sRgb = false, const IntRect& area = {});
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////
|
||||||
/// \brief Load the texture from an image
|
/// \brief Load the texture from an image
|
||||||
@ -230,132 +372,12 @@ public:
|
|||||||
/// \param sRgb True to enable sRGB conversion, false to disable it
|
/// \param sRgb True to enable sRGB conversion, false to disable it
|
||||||
/// \param area Area of the image to load
|
/// \param area Area of the image to load
|
||||||
///
|
///
|
||||||
/// \return True if loading was successful
|
/// \return True if loading was successful, false if it failed
|
||||||
///
|
///
|
||||||
/// \see loadFromFile, loadFromMemory
|
/// \see loadFromFile, loadFromMemory
|
||||||
///
|
///
|
||||||
////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////
|
||||||
[[nodiscard]] bool loadFromImage(const Image& image, bool sRgb = false, const IntRect& area = IntRect());
|
[[nodiscard]] bool loadFromImage(const Image& image, bool sRgb = false, const IntRect& area = {});
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////
|
|
||||||
/// \brief Create a texture
|
|
||||||
///
|
|
||||||
/// \param size Width and height of the texture
|
|
||||||
/// \param sRgb True to enable sRGB conversion, false to disable it
|
|
||||||
///
|
|
||||||
/// \return Texture if creation was successful, otherwise `std::nullopt`
|
|
||||||
///
|
|
||||||
////////////////////////////////////////////////////////////
|
|
||||||
[[nodiscard]] static std::optional<Texture> create(Vector2u size, bool sRgb = false);
|
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////
|
|
||||||
/// \brief Load the texture from a file on disk
|
|
||||||
///
|
|
||||||
/// The \a area argument can be used to load only a sub-rectangle
|
|
||||||
/// of the whole image. If you want the entire image then leave
|
|
||||||
/// the default value (which is an empty IntRect).
|
|
||||||
/// If the \a area rectangle crosses the bounds of the image, it
|
|
||||||
/// is adjusted to fit the image size.
|
|
||||||
///
|
|
||||||
/// The maximum size for a texture depends on the graphics
|
|
||||||
/// driver and can be retrieved with the getMaximumSize function.
|
|
||||||
///
|
|
||||||
/// If this function fails, the texture is left unchanged.
|
|
||||||
///
|
|
||||||
/// \param filename Path of the image file to load
|
|
||||||
/// \param sRgb True to enable sRGB conversion, false to disable it
|
|
||||||
/// \param area Area of the image to load
|
|
||||||
///
|
|
||||||
/// \return Texture if loading was successful, otherwise `std::nullopt`
|
|
||||||
///
|
|
||||||
/// \see createFromMemory, createFromStream, createFromImage
|
|
||||||
///
|
|
||||||
////////////////////////////////////////////////////////////
|
|
||||||
[[nodiscard]] static std::optional<Texture> createFromFile(const std::filesystem::path& filename,
|
|
||||||
bool sRgb = false,
|
|
||||||
const IntRect& area = {});
|
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////
|
|
||||||
/// \brief Load the texture from a file in memory
|
|
||||||
///
|
|
||||||
/// The \a area argument can be used to load only a sub-rectangle
|
|
||||||
/// of the whole image. If you want the entire image then leave
|
|
||||||
/// the default value (which is an empty IntRect).
|
|
||||||
/// If the \a area rectangle crosses the bounds of the image, it
|
|
||||||
/// is adjusted to fit the image size.
|
|
||||||
///
|
|
||||||
/// The maximum size for a texture depends on the graphics
|
|
||||||
/// driver and can be retrieved with the getMaximumSize function.
|
|
||||||
///
|
|
||||||
/// If this function fails, the texture is left unchanged.
|
|
||||||
///
|
|
||||||
/// \param data Pointer to the file data in memory
|
|
||||||
/// \param size Size of the data to load, in bytes
|
|
||||||
/// \param sRgb True to enable sRGB conversion, false to disable it
|
|
||||||
/// \param area Area of the image to load
|
|
||||||
///
|
|
||||||
/// \return Texture if loading was successful, otherwise `std::nullopt`
|
|
||||||
///
|
|
||||||
/// \see createFromFile, createFromStream, createFromImage
|
|
||||||
///
|
|
||||||
////////////////////////////////////////////////////////////
|
|
||||||
[[nodiscard]] static std::optional<Texture> createFromMemory(
|
|
||||||
const void* data,
|
|
||||||
std::size_t size,
|
|
||||||
bool sRgb = false,
|
|
||||||
const IntRect& area = {});
|
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////
|
|
||||||
/// \brief Load the texture from a custom stream
|
|
||||||
///
|
|
||||||
/// The \a area argument can be used to load only a sub-rectangle
|
|
||||||
/// of the whole image. If you want the entire image then leave
|
|
||||||
/// the default value (which is an empty IntRect).
|
|
||||||
/// If the \a area rectangle crosses the bounds of the image, it
|
|
||||||
/// is adjusted to fit the image size.
|
|
||||||
///
|
|
||||||
/// The maximum size for a texture depends on the graphics
|
|
||||||
/// driver and can be retrieved with the getMaximumSize function.
|
|
||||||
///
|
|
||||||
/// If this function fails, the texture is left unchanged.
|
|
||||||
///
|
|
||||||
/// \param stream Source stream to read from
|
|
||||||
/// \param sRgb True to enable sRGB conversion, false to disable it
|
|
||||||
/// \param area Area of the image to load
|
|
||||||
///
|
|
||||||
/// \return Texture if loading was successful, otherwise `std::nullopt`
|
|
||||||
///
|
|
||||||
/// \see createFromFile, createFromMemory, createFromImage
|
|
||||||
///
|
|
||||||
////////////////////////////////////////////////////////////
|
|
||||||
[[nodiscard]] static std::optional<Texture> createFromStream(InputStream& stream,
|
|
||||||
bool sRgb = false,
|
|
||||||
const IntRect& area = {});
|
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////
|
|
||||||
/// \brief Load the texture from an image
|
|
||||||
///
|
|
||||||
/// The \a area argument can be used to load only a sub-rectangle
|
|
||||||
/// of the whole image. If you want the entire image then leave
|
|
||||||
/// the default value (which is an empty IntRect).
|
|
||||||
/// If the \a area rectangle crosses the bounds of the image, it
|
|
||||||
/// is adjusted to fit the image size.
|
|
||||||
///
|
|
||||||
/// The maximum size for a texture depends on the graphics
|
|
||||||
/// driver and can be retrieved with the getMaximumSize function.
|
|
||||||
///
|
|
||||||
/// If this function fails, the texture is left unchanged.
|
|
||||||
///
|
|
||||||
/// \param image Image to load into the texture
|
|
||||||
/// \param sRgb True to enable sRGB conversion, false to disable it
|
|
||||||
/// \param area Area of the image to load
|
|
||||||
///
|
|
||||||
/// \return Texture if loading was successful, otherwise `std::nullopt`
|
|
||||||
///
|
|
||||||
/// \see createFromFile, createFromMemory
|
|
||||||
///
|
|
||||||
////////////////////////////////////////////////////////////
|
|
||||||
[[nodiscard]] static std::optional<Texture> createFromImage(const Image& image, bool sRgb = false, const IntRect& area = {});
|
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////
|
||||||
/// \brief Return the size of the texture
|
/// \brief Return the size of the texture
|
||||||
@ -375,7 +397,7 @@ public:
|
|||||||
///
|
///
|
||||||
/// \return Image containing the texture's pixels
|
/// \return Image containing the texture's pixels
|
||||||
///
|
///
|
||||||
/// \see createFromImage
|
/// \see loadFromImage
|
||||||
///
|
///
|
||||||
////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////
|
||||||
[[nodiscard]] Image copyToImage() const;
|
[[nodiscard]] Image copyToImage() const;
|
||||||
@ -771,7 +793,7 @@ SFML_GRAPHICS_API void swap(Texture& left, Texture& right) noexcept;
|
|||||||
/// However, if you want to perform some modifications on the pixels
|
/// However, if you want to perform some modifications on the pixels
|
||||||
/// before creating the final texture, you can load your file to a
|
/// before creating the final texture, you can load your file to a
|
||||||
/// sf::Image, do whatever you need with the pixels, and then call
|
/// sf::Image, do whatever you need with the pixels, and then call
|
||||||
/// Texture::createFromImage.
|
/// Texture(const Image&).
|
||||||
///
|
///
|
||||||
/// Since they live in the graphics card memory, the pixels of a texture
|
/// Since they live in the graphics card memory, the pixels of a texture
|
||||||
/// cannot be accessed without a slow copy first. And they cannot be
|
/// cannot be accessed without a slow copy first. And they cannot be
|
||||||
@ -803,7 +825,7 @@ SFML_GRAPHICS_API void swap(Texture& left, Texture& right) noexcept;
|
|||||||
/// // drawing a sprite
|
/// // drawing a sprite
|
||||||
///
|
///
|
||||||
/// // Load a texture from a file
|
/// // Load a texture from a file
|
||||||
/// const auto texture = sf::Texture::createFromFile("texture.png").value();
|
/// const sf::Texture texture("texture.png");
|
||||||
///
|
///
|
||||||
/// // Assign it to a sprite
|
/// // Assign it to a sprite
|
||||||
/// sf::Sprite sprite(texture);
|
/// sf::Sprite sprite(texture);
|
||||||
@ -817,7 +839,7 @@ SFML_GRAPHICS_API void swap(Texture& left, Texture& right) noexcept;
|
|||||||
/// // streaming real-time data, like video frames
|
/// // streaming real-time data, like video frames
|
||||||
///
|
///
|
||||||
/// // Create an empty texture
|
/// // Create an empty texture
|
||||||
/// auto texture = sf::Texture::create({640, 480}).value();
|
/// sf::Texture texture({640, 480});
|
||||||
///
|
///
|
||||||
/// // Create a sprite that will display the texture
|
/// // Create a sprite that will display the texture
|
||||||
/// sf::Sprite sprite(texture);
|
/// sf::Sprite sprite(texture);
|
||||||
|
@ -95,6 +95,16 @@ public:
|
|||||||
////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////
|
||||||
FileInputStream& operator=(FileInputStream&&) noexcept;
|
FileInputStream& operator=(FileInputStream&&) noexcept;
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////
|
||||||
|
/// \brief Construct the stream from a file path
|
||||||
|
///
|
||||||
|
/// \param filename Name of the file to open
|
||||||
|
///
|
||||||
|
/// \throws std::runtime_error on error
|
||||||
|
///
|
||||||
|
////////////////////////////////////////////////////////////
|
||||||
|
explicit FileInputStream(const std::filesystem::path& filename);
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////
|
||||||
/// \brief Open the stream from a file path
|
/// \brief Open the stream from a file path
|
||||||
///
|
///
|
||||||
@ -105,16 +115,6 @@ public:
|
|||||||
////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////
|
||||||
[[nodiscard]] bool open(const std::filesystem::path& filename);
|
[[nodiscard]] bool open(const std::filesystem::path& filename);
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////
|
|
||||||
/// \brief Create the stream from a file path
|
|
||||||
///
|
|
||||||
/// \param filename Name of the file to open
|
|
||||||
///
|
|
||||||
/// \return File input stream on success, `std::nullopt` on error
|
|
||||||
///
|
|
||||||
////////////////////////////////////////////////////////////
|
|
||||||
[[nodiscard]] static std::optional<FileInputStream> create(const std::filesystem::path& filename);
|
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////
|
||||||
/// \brief Read data from the stream
|
/// \brief Read data from the stream
|
||||||
///
|
///
|
||||||
|
@ -103,12 +103,12 @@ public:
|
|||||||
/// from which SFML can load resources.
|
/// from which SFML can load resources.
|
||||||
///
|
///
|
||||||
/// SFML resource classes like sf::Texture and
|
/// SFML resource classes like sf::Texture and
|
||||||
/// sf::SoundBuffer provide createFromFile and createFromMemory functions,
|
/// sf::SoundBuffer provide loadFromFile and loadFromMemory functions,
|
||||||
/// which read data from conventional sources. However, if you
|
/// which read data from conventional sources. However, if you
|
||||||
/// have data coming from a different source (over a network,
|
/// have data coming from a different source (over a network,
|
||||||
/// embedded, encrypted, compressed, etc) you can derive your
|
/// embedded, encrypted, compressed, etc) you can derive your
|
||||||
/// own class from sf::InputStream and load SFML resources with
|
/// own class from sf::InputStream and load SFML resources with
|
||||||
/// their createFromStream function.
|
/// their loadFromStream function.
|
||||||
///
|
///
|
||||||
/// Usage example:
|
/// Usage example:
|
||||||
/// \code
|
/// \code
|
||||||
@ -142,7 +142,7 @@ public:
|
|||||||
/// // Handle error...
|
/// // Handle error...
|
||||||
/// }
|
/// }
|
||||||
///
|
///
|
||||||
/// const auto texture = sf::Texture::createFromStream(stream).value();
|
/// const sf::Texture texture(stream);
|
||||||
///
|
///
|
||||||
/// // musics...
|
/// // musics...
|
||||||
/// sf::Music music;
|
/// sf::Music music;
|
||||||
|
@ -55,15 +55,6 @@ public:
|
|||||||
////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////
|
||||||
MemoryInputStream(const void* data, std::size_t sizeInBytes);
|
MemoryInputStream(const void* data, std::size_t sizeInBytes);
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////
|
|
||||||
/// \brief Open the stream from its data
|
|
||||||
///
|
|
||||||
/// \param data Pointer to the data in memory
|
|
||||||
/// \param sizeInBytes Size of the data, in bytes
|
|
||||||
///
|
|
||||||
////////////////////////////////////////////////////////////
|
|
||||||
void open(const void* data, std::size_t sizeInBytes);
|
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////
|
||||||
/// \brief Read data from the stream
|
/// \brief Read data from the stream
|
||||||
///
|
///
|
||||||
|
@ -144,6 +144,55 @@ public:
|
|||||||
////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////
|
||||||
Cursor& operator=(Cursor&&) noexcept;
|
Cursor& operator=(Cursor&&) noexcept;
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////
|
||||||
|
/// \brief Construct a cursor with the provided image
|
||||||
|
///
|
||||||
|
/// \a pixels must be an array of \a width by \a height pixels
|
||||||
|
/// in 32-bit RGBA format. If not, this will cause undefined behavior.
|
||||||
|
///
|
||||||
|
/// If \a pixels is null or either \a width or \a height are 0,
|
||||||
|
/// the current cursor is left unchanged and the function will
|
||||||
|
/// return false.
|
||||||
|
///
|
||||||
|
/// In addition to specifying the pixel data, you can also
|
||||||
|
/// specify the location of the hotspot of the cursor. The
|
||||||
|
/// hotspot is the pixel coordinate within the cursor image
|
||||||
|
/// which will be located exactly where the mouse pointer
|
||||||
|
/// position is. Any mouse actions that are performed will
|
||||||
|
/// return the window/screen location of the hotspot.
|
||||||
|
///
|
||||||
|
/// \warning On Unix platforms which do not support colored
|
||||||
|
/// cursors, the pixels are mapped into a monochrome
|
||||||
|
/// bitmap: pixels with an alpha channel to 0 are
|
||||||
|
/// transparent, black if the RGB channel are close
|
||||||
|
/// to zero, and white otherwise.
|
||||||
|
///
|
||||||
|
/// \param pixels Array of pixels of the image
|
||||||
|
/// \param size Width and height of the image
|
||||||
|
/// \param hotspot (x,y) location of the hotspot
|
||||||
|
///
|
||||||
|
/// \throws std::runtime_error if the cursor could not be constructed
|
||||||
|
///
|
||||||
|
////////////////////////////////////////////////////////////
|
||||||
|
Cursor(const std::uint8_t* pixels, Vector2u size, Vector2u hotspot);
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////
|
||||||
|
/// \brief Create a native system cursor
|
||||||
|
///
|
||||||
|
/// Refer to the list of cursor available on each system
|
||||||
|
/// (see sf::Cursor::Type) to know whether a given cursor is
|
||||||
|
/// expected to load successfully or is not supported by
|
||||||
|
/// the operating system.
|
||||||
|
///
|
||||||
|
/// \param type Native system cursor type
|
||||||
|
///
|
||||||
|
/// \throws std::runtime_error if the corresponding cursor
|
||||||
|
/// is not natively supported by the operating
|
||||||
|
/// system
|
||||||
|
///
|
||||||
|
////////////////////////////////////////////////////////////
|
||||||
|
explicit Cursor(Type type);
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////
|
||||||
/// \brief Create a cursor with the provided image
|
/// \brief Create a cursor with the provided image
|
||||||
///
|
///
|
||||||
|
@ -89,7 +89,7 @@ public:
|
|||||||
const String& title,
|
const String& title,
|
||||||
std::uint32_t style = Style::Default,
|
std::uint32_t style = Style::Default,
|
||||||
State state = State::Windowed,
|
State state = State::Windowed,
|
||||||
const ContextSettings& settings = ContextSettings());
|
const ContextSettings& settings = {});
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////
|
||||||
/// \brief Construct a new window
|
/// \brief Construct a new window
|
||||||
@ -108,7 +108,7 @@ public:
|
|||||||
/// \param settings Additional settings for the underlying OpenGL context
|
/// \param settings Additional settings for the underlying OpenGL context
|
||||||
///
|
///
|
||||||
////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////
|
||||||
Window(VideoMode mode, const String& title, State state, const ContextSettings& settings = ContextSettings());
|
Window(VideoMode mode, const String& title, State state, const ContextSettings& settings = {});
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////
|
||||||
/// \brief Construct the window from an existing control
|
/// \brief Construct the window from an existing control
|
||||||
@ -124,7 +124,7 @@ public:
|
|||||||
/// \param settings Additional settings for the underlying OpenGL context
|
/// \param settings Additional settings for the underlying OpenGL context
|
||||||
///
|
///
|
||||||
////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////
|
||||||
explicit Window(WindowHandle handle, const ContextSettings& settings = ContextSettings());
|
explicit Window(WindowHandle handle, const ContextSettings& settings = {});
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////
|
||||||
/// \brief Destructor
|
/// \brief Destructor
|
||||||
|
@ -66,6 +66,30 @@ void InputSoundFile::StreamDeleter::operator()(InputStream* ptr) const
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////
|
||||||
|
InputSoundFile::InputSoundFile(const std::filesystem::path& filename)
|
||||||
|
{
|
||||||
|
if (!openFromFile(filename))
|
||||||
|
throw std::runtime_error("Failed to open input sound file");
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////
|
||||||
|
InputSoundFile::InputSoundFile(const void* data, std::size_t sizeInBytes)
|
||||||
|
{
|
||||||
|
if (!openFromMemory(data, sizeInBytes))
|
||||||
|
throw std::runtime_error("Failed to open input sound file from memory");
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////
|
||||||
|
InputSoundFile::InputSoundFile(InputStream& stream)
|
||||||
|
{
|
||||||
|
if (!openFromStream(stream))
|
||||||
|
throw std::runtime_error("Failed to open input sound file from stream");
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////
|
||||||
bool InputSoundFile::openFromFile(const std::filesystem::path& filename)
|
bool InputSoundFile::openFromFile(const std::filesystem::path& filename)
|
||||||
{
|
{
|
||||||
@ -192,42 +216,6 @@ bool InputSoundFile::openFromStream(InputStream& stream)
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////
|
|
||||||
std::optional<InputSoundFile> InputSoundFile::createFromFile(const std::filesystem::path& filename)
|
|
||||||
{
|
|
||||||
auto inputSoundFile = std::make_optional<InputSoundFile>();
|
|
||||||
|
|
||||||
if (!inputSoundFile->openFromFile(filename))
|
|
||||||
return std::nullopt;
|
|
||||||
|
|
||||||
return inputSoundFile;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////
|
|
||||||
std::optional<InputSoundFile> InputSoundFile::createFromMemory(const void* data, std::size_t sizeInBytes)
|
|
||||||
{
|
|
||||||
auto inputSoundFile = std::make_optional<InputSoundFile>();
|
|
||||||
|
|
||||||
if (!inputSoundFile->openFromMemory(data, sizeInBytes))
|
|
||||||
return std::nullopt;
|
|
||||||
|
|
||||||
return inputSoundFile;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////
|
|
||||||
std::optional<InputSoundFile> InputSoundFile::createFromStream(InputStream& stream)
|
|
||||||
{
|
|
||||||
auto inputSoundFile = std::make_optional<InputSoundFile>();
|
|
||||||
|
|
||||||
if (!inputSoundFile->openFromStream(stream))
|
|
||||||
return std::nullopt;
|
|
||||||
|
|
||||||
return inputSoundFile;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////
|
||||||
std::uint64_t InputSoundFile::getSampleCount() const
|
std::uint64_t InputSoundFile::getSampleCount() const
|
||||||
{
|
{
|
||||||
|
@ -64,6 +64,30 @@ Music::Music() : m_impl(std::make_unique<Impl>())
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////
|
||||||
|
Music::Music(const std::filesystem::path& filename) : Music()
|
||||||
|
{
|
||||||
|
if (!openFromFile(filename))
|
||||||
|
throw std::runtime_error("Failed to open music from file");
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////
|
||||||
|
Music::Music(const void* data, std::size_t sizeInBytes) : Music()
|
||||||
|
{
|
||||||
|
if (!openFromMemory(data, sizeInBytes))
|
||||||
|
throw std::runtime_error("Failed to open music from memory");
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////
|
||||||
|
Music::Music(InputStream& stream) : Music()
|
||||||
|
{
|
||||||
|
if (!openFromStream(stream))
|
||||||
|
throw std::runtime_error("Failed to open music from stream");
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////
|
||||||
Music::~Music()
|
Music::~Music()
|
||||||
{
|
{
|
||||||
@ -152,42 +176,6 @@ bool Music::openFromStream(InputStream& stream)
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////
|
|
||||||
std::optional<Music> Music::createFromFile(const std::filesystem::path& filename)
|
|
||||||
{
|
|
||||||
auto music = std::make_optional<Music>();
|
|
||||||
|
|
||||||
if (!music->openFromFile(filename))
|
|
||||||
return std::nullopt;
|
|
||||||
|
|
||||||
return music;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////
|
|
||||||
std::optional<Music> Music::createFromMemory(const void* data, std::size_t sizeInBytes)
|
|
||||||
{
|
|
||||||
auto music = std::make_optional<Music>();
|
|
||||||
|
|
||||||
if (!music->openFromMemory(data, sizeInBytes))
|
|
||||||
return std::nullopt;
|
|
||||||
|
|
||||||
return music;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////
|
|
||||||
std::optional<Music> Music::createFromStream(InputStream& stream)
|
|
||||||
{
|
|
||||||
auto music = std::make_optional<Music>();
|
|
||||||
|
|
||||||
if (!music->openFromStream(stream))
|
|
||||||
return std::nullopt;
|
|
||||||
|
|
||||||
return music;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////
|
||||||
Time Music::getDuration() const
|
Time Music::getDuration() const
|
||||||
{
|
{
|
||||||
|
@ -36,6 +36,17 @@
|
|||||||
|
|
||||||
namespace sf
|
namespace sf
|
||||||
{
|
{
|
||||||
|
////////////////////////////////////////////////////////////
|
||||||
|
OutputSoundFile::OutputSoundFile(const std::filesystem::path& filename,
|
||||||
|
unsigned int sampleRate,
|
||||||
|
unsigned int channelCount,
|
||||||
|
const std::vector<SoundChannel>& channelMap)
|
||||||
|
{
|
||||||
|
if (!openFromFile(filename, sampleRate, channelCount, channelMap))
|
||||||
|
throw std::runtime_error("Failed to open output sound file");
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////
|
||||||
bool OutputSoundFile::openFromFile(const std::filesystem::path& filename,
|
bool OutputSoundFile::openFromFile(const std::filesystem::path& filename,
|
||||||
unsigned int sampleRate,
|
unsigned int sampleRate,
|
||||||
@ -65,22 +76,6 @@ bool OutputSoundFile::openFromFile(const std::filesystem::path& filename,
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////
|
|
||||||
std::optional<OutputSoundFile> OutputSoundFile::createFromFile(
|
|
||||||
const std::filesystem::path& filename,
|
|
||||||
unsigned int sampleRate,
|
|
||||||
unsigned int channelCount,
|
|
||||||
const std::vector<SoundChannel>& channelMap)
|
|
||||||
{
|
|
||||||
auto outputSoundFile = std::make_optional<OutputSoundFile>();
|
|
||||||
|
|
||||||
if (!outputSoundFile->openFromFile(filename, sampleRate, channelCount, channelMap))
|
|
||||||
return std::nullopt;
|
|
||||||
|
|
||||||
return outputSoundFile;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////
|
||||||
void OutputSoundFile::write(const std::int16_t* samples, std::uint64_t count)
|
void OutputSoundFile::write(const std::int16_t* samples, std::uint64_t count)
|
||||||
{
|
{
|
||||||
|
@ -39,6 +39,42 @@
|
|||||||
|
|
||||||
namespace sf
|
namespace sf
|
||||||
{
|
{
|
||||||
|
////////////////////////////////////////////////////////////
|
||||||
|
SoundBuffer::SoundBuffer(const std::filesystem::path& filename)
|
||||||
|
{
|
||||||
|
if (!loadFromFile(filename))
|
||||||
|
throw std::runtime_error("Failed to open sound buffer from file");
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////
|
||||||
|
SoundBuffer::SoundBuffer(const void* data, std::size_t sizeInBytes)
|
||||||
|
{
|
||||||
|
if (!loadFromMemory(data, sizeInBytes))
|
||||||
|
throw std::runtime_error("Failed to open sound buffer from memory");
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////
|
||||||
|
SoundBuffer::SoundBuffer(InputStream& stream)
|
||||||
|
{
|
||||||
|
if (!loadFromStream(stream))
|
||||||
|
throw std::runtime_error("Failed to open sound buffer from stream");
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////
|
||||||
|
SoundBuffer::SoundBuffer(const std::int16_t* samples,
|
||||||
|
std::uint64_t sampleCount,
|
||||||
|
unsigned int channelCount,
|
||||||
|
unsigned int sampleRate,
|
||||||
|
const std::vector<SoundChannel>& channelMap)
|
||||||
|
{
|
||||||
|
if (!loadFromSamples(samples, sampleCount, channelCount, sampleRate, channelMap))
|
||||||
|
throw std::runtime_error("Failed to open sound buffer from samples");
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////
|
||||||
SoundBuffer::SoundBuffer(const SoundBuffer& copy)
|
SoundBuffer::SoundBuffer(const SoundBuffer& copy)
|
||||||
{
|
{
|
||||||
@ -130,59 +166,6 @@ bool SoundBuffer::loadFromSamples(const std::int16_t* samples,
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////
|
|
||||||
std::optional<SoundBuffer> SoundBuffer::createFromFile(const std::filesystem::path& filename)
|
|
||||||
{
|
|
||||||
auto soundBuffer = std::make_optional<SoundBuffer>();
|
|
||||||
|
|
||||||
if (!soundBuffer->loadFromFile(filename))
|
|
||||||
return std::nullopt;
|
|
||||||
|
|
||||||
return soundBuffer;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////
|
|
||||||
std::optional<SoundBuffer> SoundBuffer::createFromMemory(const void* data, std::size_t sizeInBytes)
|
|
||||||
{
|
|
||||||
auto soundBuffer = std::make_optional<SoundBuffer>();
|
|
||||||
|
|
||||||
if (!soundBuffer->loadFromMemory(data, sizeInBytes))
|
|
||||||
return std::nullopt;
|
|
||||||
|
|
||||||
return soundBuffer;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////
|
|
||||||
std::optional<SoundBuffer> SoundBuffer::createFromStream(InputStream& stream)
|
|
||||||
{
|
|
||||||
auto soundBuffer = std::make_optional<SoundBuffer>();
|
|
||||||
|
|
||||||
if (!soundBuffer->loadFromStream(stream))
|
|
||||||
return std::nullopt;
|
|
||||||
|
|
||||||
return soundBuffer;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////
|
|
||||||
std::optional<SoundBuffer> SoundBuffer::createFromSamples(
|
|
||||||
const std::int16_t* samples,
|
|
||||||
std::uint64_t sampleCount,
|
|
||||||
unsigned int channelCount,
|
|
||||||
unsigned int sampleRate,
|
|
||||||
const std::vector<SoundChannel>& channelMap)
|
|
||||||
{
|
|
||||||
auto soundBuffer = std::make_optional<SoundBuffer>();
|
|
||||||
|
|
||||||
if (!soundBuffer->loadFromSamples(samples, sampleCount, channelCount, sampleRate, channelMap))
|
|
||||||
return std::nullopt;
|
|
||||||
|
|
||||||
return soundBuffer;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////
|
||||||
bool SoundBuffer::saveToFile(const std::filesystem::path& filename) const
|
bool SoundBuffer::saveToFile(const std::filesystem::path& filename) const
|
||||||
{
|
{
|
||||||
|
@ -48,7 +48,7 @@ SoundBufferRecorder::~SoundBufferRecorder()
|
|||||||
bool SoundBufferRecorder::onStart()
|
bool SoundBufferRecorder::onStart()
|
||||||
{
|
{
|
||||||
m_samples.clear();
|
m_samples.clear();
|
||||||
m_buffer = SoundBuffer();
|
m_buffer = {};
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
@ -120,6 +120,30 @@ struct Font::FontHandles
|
|||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////
|
||||||
|
Font::Font(const std::filesystem::path& filename)
|
||||||
|
{
|
||||||
|
if (!openFromFile(filename))
|
||||||
|
throw std::runtime_error("Failed to open font from file");
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////
|
||||||
|
Font::Font(const void* data, std::size_t sizeInBytes)
|
||||||
|
{
|
||||||
|
if (!openFromMemory(data, sizeInBytes))
|
||||||
|
throw std::runtime_error("Failed to open font from memory");
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////
|
||||||
|
Font::Font(InputStream& stream)
|
||||||
|
{
|
||||||
|
if (!openFromStream(stream))
|
||||||
|
throw std::runtime_error("Failed to open font from stream");
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////
|
||||||
bool Font::openFromFile(const std::filesystem::path& filename)
|
bool Font::openFromFile(const std::filesystem::path& filename)
|
||||||
{
|
{
|
||||||
@ -252,7 +276,7 @@ bool Font::openFromStream(InputStream& stream)
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Make sure that the stream's reading position is at the beginning
|
// Make sure that the stream's reading position is at the beginning
|
||||||
if (!stream.seek(0))
|
if (!stream.seek(0).has_value())
|
||||||
{
|
{
|
||||||
err() << "Failed to seek font stream" << std::endl;
|
err() << "Failed to seek font stream" << std::endl;
|
||||||
return false;
|
return false;
|
||||||
@ -305,42 +329,6 @@ bool Font::openFromStream(InputStream& stream)
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////
|
|
||||||
std::optional<Font> Font::createFromFile(const std::filesystem::path& filename)
|
|
||||||
{
|
|
||||||
auto font = std::make_optional<Font>();
|
|
||||||
|
|
||||||
if (!font->openFromFile(filename))
|
|
||||||
return std::nullopt;
|
|
||||||
|
|
||||||
return font;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////
|
|
||||||
std::optional<Font> Font::createFromMemory(const void* data, std::size_t sizeInBytes)
|
|
||||||
{
|
|
||||||
auto font = std::make_optional<Font>();
|
|
||||||
|
|
||||||
if (!font->openFromMemory(data, sizeInBytes))
|
|
||||||
return std::nullopt;
|
|
||||||
|
|
||||||
return font;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////
|
|
||||||
std::optional<Font> Font::createFromStream(InputStream& stream)
|
|
||||||
{
|
|
||||||
auto font = std::make_optional<Font>();
|
|
||||||
|
|
||||||
if (!font->openFromStream(stream))
|
|
||||||
return std::nullopt;
|
|
||||||
|
|
||||||
return font;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////
|
||||||
const Font::Info& Font::getInfo() const
|
const Font::Info& Font::getInfo() const
|
||||||
{
|
{
|
||||||
@ -409,8 +397,7 @@ float Font::getKerning(std::uint32_t first, std::uint32_t second, unsigned int c
|
|||||||
|
|
||||||
// Combine kerning with compensation deltas and return the X advance
|
// Combine kerning with compensation deltas and return the X advance
|
||||||
// Flooring is required as we use FT_KERNING_UNFITTED flag which is not quantized in 64 based grid
|
// Flooring is required as we use FT_KERNING_UNFITTED flag which is not quantized in 64 based grid
|
||||||
return std::floor(
|
return std::floor((secondLsbDelta - firstRsbDelta + static_cast<float>(kerning.x) + 32) / float{1 << 6});
|
||||||
(secondLsbDelta - firstRsbDelta + static_cast<float>(kerning.x) + 32) / static_cast<float>(1 << 6));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Invalid font
|
// Invalid font
|
||||||
@ -425,7 +412,7 @@ float Font::getLineSpacing(unsigned int characterSize) const
|
|||||||
|
|
||||||
if (face && setCurrentSize(characterSize))
|
if (face && setCurrentSize(characterSize))
|
||||||
{
|
{
|
||||||
return static_cast<float>(face->size->metrics.height) / static_cast<float>(1 << 6);
|
return static_cast<float>(face->size->metrics.height) / float{1 << 6};
|
||||||
}
|
}
|
||||||
|
|
||||||
return 0.f;
|
return 0.f;
|
||||||
@ -443,8 +430,7 @@ float Font::getUnderlinePosition(unsigned int characterSize) const
|
|||||||
if (!FT_IS_SCALABLE(face))
|
if (!FT_IS_SCALABLE(face))
|
||||||
return static_cast<float>(characterSize) / 10.f;
|
return static_cast<float>(characterSize) / 10.f;
|
||||||
|
|
||||||
return -static_cast<float>(FT_MulFix(face->underline_position, face->size->metrics.y_scale)) /
|
return -static_cast<float>(FT_MulFix(face->underline_position, face->size->metrics.y_scale)) / float{1 << 6};
|
||||||
static_cast<float>(1 << 6);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return 0.f;
|
return 0.f;
|
||||||
@ -462,8 +448,7 @@ float Font::getUnderlineThickness(unsigned int characterSize) const
|
|||||||
if (!FT_IS_SCALABLE(face))
|
if (!FT_IS_SCALABLE(face))
|
||||||
return static_cast<float>(characterSize) / 14.f;
|
return static_cast<float>(characterSize) / 14.f;
|
||||||
|
|
||||||
return static_cast<float>(FT_MulFix(face->underline_thickness, face->size->metrics.y_scale)) /
|
return static_cast<float>(FT_MulFix(face->underline_thickness, face->size->metrics.y_scale)) / float{1 << 6};
|
||||||
static_cast<float>(1 << 6);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return 0.f;
|
return 0.f;
|
||||||
@ -563,7 +548,7 @@ Glyph Font::loadGlyph(std::uint32_t codePoint, unsigned int characterSize, bool
|
|||||||
FT_Stroker stroker = m_fontHandles->stroker;
|
FT_Stroker stroker = m_fontHandles->stroker;
|
||||||
|
|
||||||
FT_Stroker_Set(stroker,
|
FT_Stroker_Set(stroker,
|
||||||
static_cast<FT_Fixed>(outlineThickness * static_cast<float>(1 << 6)),
|
static_cast<FT_Fixed>(outlineThickness * float{1 << 6}),
|
||||||
FT_STROKER_LINECAP_ROUND,
|
FT_STROKER_LINECAP_ROUND,
|
||||||
FT_STROKER_LINEJOIN_ROUND,
|
FT_STROKER_LINEJOIN_ROUND,
|
||||||
0);
|
0);
|
||||||
@ -591,47 +576,41 @@ Glyph Font::loadGlyph(std::uint32_t codePoint, unsigned int characterSize, bool
|
|||||||
// Compute the glyph's advance offset
|
// Compute the glyph's advance offset
|
||||||
glyph.advance = static_cast<float>(bitmapGlyph->root.advance.x >> 16);
|
glyph.advance = static_cast<float>(bitmapGlyph->root.advance.x >> 16);
|
||||||
if (bold)
|
if (bold)
|
||||||
glyph.advance += static_cast<float>(weight) / static_cast<float>(1 << 6);
|
glyph.advance += static_cast<float>(weight) / float{1 << 6};
|
||||||
|
|
||||||
glyph.lsbDelta = static_cast<int>(face->glyph->lsb_delta);
|
glyph.lsbDelta = static_cast<int>(face->glyph->lsb_delta);
|
||||||
glyph.rsbDelta = static_cast<int>(face->glyph->rsb_delta);
|
glyph.rsbDelta = static_cast<int>(face->glyph->rsb_delta);
|
||||||
|
|
||||||
unsigned int width = bitmap.width;
|
Vector2u size(bitmap.width, bitmap.rows);
|
||||||
unsigned int height = bitmap.rows;
|
|
||||||
|
|
||||||
if ((width > 0) && (height > 0))
|
if ((size.x > 0) && (size.y > 0))
|
||||||
{
|
{
|
||||||
// Leave a small padding around characters, so that filtering doesn't
|
// Leave a small padding around characters, so that filtering doesn't
|
||||||
// pollute them with pixels from neighbors
|
// pollute them with pixels from neighbors
|
||||||
const unsigned int padding = 2;
|
const unsigned int padding = 2;
|
||||||
|
|
||||||
width += 2 * padding;
|
size += 2u * Vector2u(padding, padding);
|
||||||
height += 2 * padding;
|
|
||||||
|
|
||||||
// Get the glyphs page corresponding to the character size
|
// Get the glyphs page corresponding to the character size
|
||||||
Page& page = loadPage(characterSize);
|
Page& page = loadPage(characterSize);
|
||||||
|
|
||||||
// Find a good position for the new glyph into the texture
|
// Find a good position for the new glyph into the texture
|
||||||
glyph.textureRect = findGlyphRect(page, {width, height});
|
glyph.textureRect = findGlyphRect(page, size);
|
||||||
|
|
||||||
// Make sure the texture data is positioned in the center
|
// Make sure the texture data is positioned in the center
|
||||||
// of the allocated texture rectangle
|
// of the allocated texture rectangle
|
||||||
glyph.textureRect.position.x += static_cast<int>(padding);
|
glyph.textureRect.position += Vector2i(padding, padding);
|
||||||
glyph.textureRect.position.y += static_cast<int>(padding);
|
glyph.textureRect.size -= 2 * Vector2i(padding, padding);
|
||||||
glyph.textureRect.size.x -= static_cast<int>(2 * padding);
|
|
||||||
glyph.textureRect.size.y -= static_cast<int>(2 * padding);
|
|
||||||
|
|
||||||
// Compute the glyph's bounding box
|
// Compute the glyph's bounding box
|
||||||
glyph.bounds.position.x = static_cast<float>(bitmapGlyph->left);
|
glyph.bounds.position = Vector2f(Vector2i(bitmapGlyph->left, -bitmapGlyph->top));
|
||||||
glyph.bounds.position.y = static_cast<float>(-bitmapGlyph->top);
|
glyph.bounds.size = Vector2f(Vector2u(bitmap.width, bitmap.rows));
|
||||||
glyph.bounds.size.x = static_cast<float>(bitmap.width);
|
|
||||||
glyph.bounds.size.y = static_cast<float>(bitmap.rows);
|
|
||||||
|
|
||||||
// Resize the pixel buffer to the new size and fill it with transparent white pixels
|
// Resize the pixel buffer to the new size and fill it with transparent white pixels
|
||||||
m_pixelBuffer.resize(static_cast<std::size_t>(width) * static_cast<std::size_t>(height) * 4);
|
m_pixelBuffer.resize(static_cast<std::size_t>(size.x) * static_cast<std::size_t>(size.y) * 4);
|
||||||
|
|
||||||
std::uint8_t* current = m_pixelBuffer.data();
|
std::uint8_t* current = m_pixelBuffer.data();
|
||||||
std::uint8_t* end = current + width * height * 4;
|
std::uint8_t* end = current + size.x * size.y * 4;
|
||||||
|
|
||||||
while (current != end)
|
while (current != end)
|
||||||
{
|
{
|
||||||
@ -646,12 +625,12 @@ Glyph Font::loadGlyph(std::uint32_t codePoint, unsigned int characterSize, bool
|
|||||||
if (bitmap.pixel_mode == FT_PIXEL_MODE_MONO)
|
if (bitmap.pixel_mode == FT_PIXEL_MODE_MONO)
|
||||||
{
|
{
|
||||||
// Pixels are 1 bit monochrome values
|
// Pixels are 1 bit monochrome values
|
||||||
for (unsigned int y = padding; y < height - padding; ++y)
|
for (unsigned int y = padding; y < size.y - padding; ++y)
|
||||||
{
|
{
|
||||||
for (unsigned int x = padding; x < width - padding; ++x)
|
for (unsigned int x = padding; x < size.x - padding; ++x)
|
||||||
{
|
{
|
||||||
// The color channels remain white, just fill the alpha channel
|
// The color channels remain white, just fill the alpha channel
|
||||||
const std::size_t index = x + y * width;
|
const std::size_t index = x + y * size.x;
|
||||||
m_pixelBuffer[index * 4 + 3] = ((pixels[(x - padding) / 8]) & (1 << (7 - ((x - padding) % 8)))) ? 255 : 0;
|
m_pixelBuffer[index * 4 + 3] = ((pixels[(x - padding) / 8]) & (1 << (7 - ((x - padding) % 8)))) ? 255 : 0;
|
||||||
}
|
}
|
||||||
pixels += bitmap.pitch;
|
pixels += bitmap.pitch;
|
||||||
@ -659,13 +638,13 @@ Glyph Font::loadGlyph(std::uint32_t codePoint, unsigned int characterSize, bool
|
|||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
// Pixels are 8 bits gray levels
|
// Pixels are 8 bit gray levels
|
||||||
for (unsigned int y = padding; y < height - padding; ++y)
|
for (unsigned int y = padding; y < size.y - padding; ++y)
|
||||||
{
|
{
|
||||||
for (unsigned int x = padding; x < width - padding; ++x)
|
for (unsigned int x = padding; x < size.x - padding; ++x)
|
||||||
{
|
{
|
||||||
// The color channels remain white, just fill the alpha channel
|
// The color channels remain white, just fill the alpha channel
|
||||||
const std::size_t index = x + y * width;
|
const std::size_t index = x + y * size.x;
|
||||||
m_pixelBuffer[index * 4 + 3] = pixels[x - padding];
|
m_pixelBuffer[index * 4 + 3] = pixels[x - padding];
|
||||||
}
|
}
|
||||||
pixels += bitmap.pitch;
|
pixels += bitmap.pitch;
|
||||||
@ -673,11 +652,9 @@ Glyph Font::loadGlyph(std::uint32_t codePoint, unsigned int characterSize, bool
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Write the pixels to the texture
|
// Write the pixels to the texture
|
||||||
const unsigned int x = static_cast<unsigned int>(glyph.textureRect.position.x) - padding;
|
const auto dest = Vector2u(glyph.textureRect.position) - Vector2u(padding, padding);
|
||||||
const unsigned int y = static_cast<unsigned int>(glyph.textureRect.position.y) - padding;
|
const auto updateSize = Vector2u(glyph.textureRect.size) + 2u * Vector2u(padding, padding);
|
||||||
const unsigned int w = static_cast<unsigned int>(glyph.textureRect.size.x) + 2 * padding;
|
page.texture.update(m_pixelBuffer.data(), updateSize, dest);
|
||||||
const unsigned int h = static_cast<unsigned int>(glyph.textureRect.size.y) + 2 * padding;
|
|
||||||
page.texture.update(m_pixelBuffer.data(), {w, h}, {x, y});
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Delete the FT glyph
|
// Delete the FT glyph
|
||||||
|
@ -109,6 +109,30 @@ Image::Image(Vector2u size, const std::uint8_t* pixels)
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////
|
||||||
|
Image::Image(const std::filesystem::path& filename)
|
||||||
|
{
|
||||||
|
if (!loadFromFile(filename))
|
||||||
|
throw std::runtime_error("Failed to open image from file");
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////
|
||||||
|
Image::Image(const void* data, std::size_t size)
|
||||||
|
{
|
||||||
|
if (!loadFromMemory(data, size))
|
||||||
|
throw std::runtime_error("Failed to open image from memory");
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////
|
||||||
|
Image::Image(InputStream& stream)
|
||||||
|
{
|
||||||
|
if (!loadFromStream(stream))
|
||||||
|
throw std::runtime_error("Failed to open image from stream");
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////
|
||||||
void Image::resize(Vector2u size, Color color)
|
void Image::resize(Vector2u size, Color color)
|
||||||
{
|
{
|
||||||
@ -257,7 +281,7 @@ bool Image::loadFromStream(InputStream& stream)
|
|||||||
m_pixels.clear();
|
m_pixels.clear();
|
||||||
|
|
||||||
// Make sure that the stream's reading position is at the beginning
|
// Make sure that the stream's reading position is at the beginning
|
||||||
if (!stream.seek(0))
|
if (!stream.seek(0).has_value())
|
||||||
{
|
{
|
||||||
err() << "Failed to seek image stream" << std::endl;
|
err() << "Failed to seek image stream" << std::endl;
|
||||||
return false;
|
return false;
|
||||||
@ -292,42 +316,6 @@ bool Image::loadFromStream(InputStream& stream)
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////
|
|
||||||
std::optional<Image> Image::createFromFile(const std::filesystem::path& filename)
|
|
||||||
{
|
|
||||||
auto image = std::make_optional<Image>();
|
|
||||||
|
|
||||||
if (!image->loadFromFile(filename))
|
|
||||||
return std::nullopt;
|
|
||||||
|
|
||||||
return image;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////
|
|
||||||
std::optional<Image> Image::createFromMemory(const void* data, std::size_t size)
|
|
||||||
{
|
|
||||||
auto image = std::make_optional<Image>();
|
|
||||||
|
|
||||||
if (!image->loadFromMemory(data, size))
|
|
||||||
return std::nullopt;
|
|
||||||
|
|
||||||
return image;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////
|
|
||||||
std::optional<Image> Image::createFromStream(InputStream& stream)
|
|
||||||
{
|
|
||||||
auto image = std::make_optional<Image>();
|
|
||||||
|
|
||||||
if (!image->loadFromStream(stream))
|
|
||||||
return std::nullopt;
|
|
||||||
|
|
||||||
return image;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////
|
||||||
bool Image::saveToFile(const std::filesystem::path& filename) const
|
bool Image::saveToFile(const std::filesystem::path& filename) const
|
||||||
{
|
{
|
||||||
|
@ -43,6 +43,14 @@ namespace sf
|
|||||||
RenderTexture::RenderTexture() = default;
|
RenderTexture::RenderTexture() = default;
|
||||||
|
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////
|
||||||
|
RenderTexture::RenderTexture(Vector2u size, const ContextSettings& settings)
|
||||||
|
{
|
||||||
|
if (!resize(size, settings))
|
||||||
|
throw std::runtime_error("Failed to create render texture");
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////
|
||||||
RenderTexture::~RenderTexture() = default;
|
RenderTexture::~RenderTexture() = default;
|
||||||
|
|
||||||
@ -96,18 +104,6 @@ bool RenderTexture::resize(Vector2u size, const ContextSettings& settings)
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////
|
|
||||||
std::optional<RenderTexture> RenderTexture::create(Vector2u size, const ContextSettings& settings)
|
|
||||||
{
|
|
||||||
auto renderTexture = std::make_optional<RenderTexture>();
|
|
||||||
|
|
||||||
if (!renderTexture->resize(size, settings))
|
|
||||||
return std::nullopt;
|
|
||||||
|
|
||||||
return renderTexture;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////
|
||||||
unsigned int RenderTexture::getMaximumAntialiasingLevel()
|
unsigned int RenderTexture::getMaximumAntialiasingLevel()
|
||||||
{
|
{
|
||||||
@ -169,26 +165,26 @@ bool RenderTexture::setActive(bool active)
|
|||||||
////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////
|
||||||
void RenderTexture::display()
|
void RenderTexture::display()
|
||||||
{
|
{
|
||||||
if (m_impl)
|
if (!m_impl)
|
||||||
{
|
return;
|
||||||
if (priv::RenderTextureImplFBO::isAvailable())
|
|
||||||
{
|
|
||||||
// Perform a RenderTarget-only activation if we are using FBOs
|
|
||||||
if (!RenderTarget::setActive())
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
// Perform a full activation if we are not using FBOs
|
|
||||||
if (!setActive())
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Update the target texture
|
if (priv::RenderTextureImplFBO::isAvailable())
|
||||||
m_impl->updateTexture(m_texture.m_texture);
|
{
|
||||||
m_texture.m_pixelsFlipped = true;
|
// Perform a RenderTarget-only activation if we are using FBOs
|
||||||
m_texture.invalidateMipmap();
|
if (!RenderTarget::setActive())
|
||||||
|
return;
|
||||||
}
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
// Perform a full activation if we are not using FBOs
|
||||||
|
if (!setActive())
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Update the target texture
|
||||||
|
m_impl->updateTexture(m_texture.m_texture);
|
||||||
|
m_texture.m_pixelsFlipped = true;
|
||||||
|
m_texture.invalidateMipmap();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -202,7 +198,7 @@ Vector2u RenderTexture::getSize() const
|
|||||||
////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////
|
||||||
bool RenderTexture::isSrgb() const
|
bool RenderTexture::isSrgb() const
|
||||||
{
|
{
|
||||||
assert(m_impl && "Must call RenderTexture::create first");
|
assert(m_impl && "RenderTexture::isSrgb() Must first initialize render texture");
|
||||||
return m_impl->isSrgb();
|
return m_impl->isSrgb();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -223,6 +223,80 @@ struct Shader::UniformBinder
|
|||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////
|
||||||
|
Shader::Shader(const std::filesystem::path& filename, Type type)
|
||||||
|
{
|
||||||
|
if (!loadFromFile(filename, type))
|
||||||
|
throw std::runtime_error("Failed to load shader from file");
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////
|
||||||
|
Shader::Shader(const std::filesystem::path& vertexShaderFilename, const std::filesystem::path& fragmentShaderFilename)
|
||||||
|
{
|
||||||
|
if (!loadFromFile(vertexShaderFilename, fragmentShaderFilename))
|
||||||
|
throw std::runtime_error("Failed to load shader from files");
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////
|
||||||
|
Shader::Shader(const std::filesystem::path& vertexShaderFilename,
|
||||||
|
const std::filesystem::path& geometryShaderFilename,
|
||||||
|
const std::filesystem::path& fragmentShaderFilename)
|
||||||
|
{
|
||||||
|
if (!loadFromFile(vertexShaderFilename, geometryShaderFilename, fragmentShaderFilename))
|
||||||
|
throw std::runtime_error("Failed to load shader from files");
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////
|
||||||
|
Shader::Shader(std::string_view shader, Type type)
|
||||||
|
{
|
||||||
|
if (!loadFromMemory(shader, type))
|
||||||
|
throw std::runtime_error("Failed to load shader from memory");
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////
|
||||||
|
Shader::Shader(std::string_view vertexShader, std::string_view fragmentShader)
|
||||||
|
{
|
||||||
|
if (!loadFromMemory(vertexShader, fragmentShader))
|
||||||
|
throw std::runtime_error("Failed to load shader from memory");
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////
|
||||||
|
Shader::Shader(std::string_view vertexShader, std::string_view geometryShader, std::string_view fragmentShader)
|
||||||
|
{
|
||||||
|
if (!loadFromMemory(vertexShader, geometryShader, fragmentShader))
|
||||||
|
throw std::runtime_error("Failed to load shader from memory");
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////
|
||||||
|
Shader::Shader(InputStream& stream, Type type)
|
||||||
|
{
|
||||||
|
if (!loadFromStream(stream, type))
|
||||||
|
throw std::runtime_error("Failed to load shader from stream");
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////
|
||||||
|
Shader::Shader(InputStream& vertexShaderStream, InputStream& fragmentShaderStream)
|
||||||
|
{
|
||||||
|
if (!loadFromStream(vertexShaderStream, fragmentShaderStream))
|
||||||
|
throw std::runtime_error("Failed to load shader from streams");
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////
|
||||||
|
Shader::Shader(InputStream& vertexShaderStream, InputStream& geometryShaderStream, InputStream& fragmentShaderStream)
|
||||||
|
{
|
||||||
|
if (!loadFromStream(vertexShaderStream, geometryShaderStream, fragmentShaderStream))
|
||||||
|
throw std::runtime_error("Failed to load shader from streams");
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////
|
||||||
Shader::~Shader()
|
Shader::~Shader()
|
||||||
{
|
{
|
||||||
@ -455,121 +529,6 @@ bool Shader::loadFromStream(InputStream& vertexShaderStream, InputStream& geomet
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////
|
|
||||||
std::optional<Shader> Shader::createFromFile(const std::filesystem::path& filename, Type type)
|
|
||||||
{
|
|
||||||
auto shader = std::make_optional<Shader>();
|
|
||||||
|
|
||||||
if (!shader->loadFromFile(filename, type))
|
|
||||||
return std::nullopt;
|
|
||||||
|
|
||||||
return shader;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////
|
|
||||||
std::optional<Shader> Shader::createFromFile(const std::filesystem::path& vertexShaderFilename,
|
|
||||||
const std::filesystem::path& fragmentShaderFilename)
|
|
||||||
{
|
|
||||||
auto shader = std::make_optional<Shader>();
|
|
||||||
|
|
||||||
if (!shader->loadFromFile(vertexShaderFilename, fragmentShaderFilename))
|
|
||||||
return std::nullopt;
|
|
||||||
|
|
||||||
return shader;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////
|
|
||||||
std::optional<Shader> Shader::createFromFile(const std::filesystem::path& vertexShaderFilename,
|
|
||||||
const std::filesystem::path& geometryShaderFilename,
|
|
||||||
const std::filesystem::path& fragmentShaderFilename)
|
|
||||||
{
|
|
||||||
auto shader = std::make_optional<Shader>();
|
|
||||||
|
|
||||||
if (!shader->loadFromFile(vertexShaderFilename, geometryShaderFilename, fragmentShaderFilename))
|
|
||||||
return std::nullopt;
|
|
||||||
|
|
||||||
return shader;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////
|
|
||||||
std::optional<Shader> Shader::createFromMemory(std::string_view shader, Type type)
|
|
||||||
{
|
|
||||||
auto newShader = std::make_optional<Shader>();
|
|
||||||
|
|
||||||
if (!newShader->loadFromMemory(shader, type))
|
|
||||||
return std::nullopt;
|
|
||||||
|
|
||||||
return newShader;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////
|
|
||||||
std::optional<Shader> Shader::createFromMemory(std::string_view vertexShader, std::string_view fragmentShader)
|
|
||||||
{
|
|
||||||
auto shader = std::make_optional<Shader>();
|
|
||||||
|
|
||||||
if (!shader->loadFromMemory(vertexShader, fragmentShader))
|
|
||||||
return std::nullopt;
|
|
||||||
|
|
||||||
return shader;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////
|
|
||||||
std::optional<Shader> Shader::createFromMemory(std::string_view vertexShader,
|
|
||||||
std::string_view geometryShader,
|
|
||||||
std::string_view fragmentShader)
|
|
||||||
{
|
|
||||||
auto shader = std::make_optional<Shader>();
|
|
||||||
|
|
||||||
if (!shader->loadFromMemory(vertexShader, geometryShader, fragmentShader))
|
|
||||||
return std::nullopt;
|
|
||||||
|
|
||||||
return shader;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////
|
|
||||||
std::optional<Shader> Shader::createFromStream(InputStream& stream, Type type)
|
|
||||||
{
|
|
||||||
auto shader = std::make_optional<Shader>();
|
|
||||||
|
|
||||||
if (!shader->loadFromStream(stream, type))
|
|
||||||
return std::nullopt;
|
|
||||||
|
|
||||||
return shader;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////
|
|
||||||
std::optional<Shader> Shader::createFromStream(InputStream& vertexShaderStream, InputStream& fragmentShaderStream)
|
|
||||||
{
|
|
||||||
auto shader = std::make_optional<Shader>();
|
|
||||||
|
|
||||||
if (!shader->loadFromStream(vertexShaderStream, fragmentShaderStream))
|
|
||||||
return std::nullopt;
|
|
||||||
|
|
||||||
return shader;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////
|
|
||||||
std::optional<Shader> Shader::createFromStream(InputStream& vertexShaderStream,
|
|
||||||
InputStream& geometryShaderStream,
|
|
||||||
InputStream& fragmentShaderStream)
|
|
||||||
{
|
|
||||||
auto shader = std::make_optional<Shader>();
|
|
||||||
|
|
||||||
if (!shader->loadFromStream(vertexShaderStream, geometryShaderStream, fragmentShaderStream))
|
|
||||||
return std::nullopt;
|
|
||||||
|
|
||||||
return shader;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////
|
||||||
void Shader::setUniform(const std::string& name, float x)
|
void Shader::setUniform(const std::string& name, float x)
|
||||||
{
|
{
|
||||||
@ -691,33 +650,33 @@ void Shader::setUniform(const std::string& name, const Glsl::Mat4& matrix)
|
|||||||
////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////
|
||||||
void Shader::setUniform(const std::string& name, const Texture& texture)
|
void Shader::setUniform(const std::string& name, const Texture& texture)
|
||||||
{
|
{
|
||||||
if (m_shaderProgram)
|
if (!m_shaderProgram)
|
||||||
|
return;
|
||||||
|
|
||||||
|
const TransientContextLock lock;
|
||||||
|
|
||||||
|
// Find the location of the variable in the shader
|
||||||
|
const int location = getUniformLocation(name);
|
||||||
|
if (location != -1)
|
||||||
{
|
{
|
||||||
const TransientContextLock lock;
|
// Store the location -> texture mapping
|
||||||
|
const auto it = m_textures.find(location);
|
||||||
// Find the location of the variable in the shader
|
if (it == m_textures.end())
|
||||||
const int location = getUniformLocation(name);
|
|
||||||
if (location != -1)
|
|
||||||
{
|
{
|
||||||
// Store the location -> texture mapping
|
// New entry, make sure there are enough texture units
|
||||||
const auto it = m_textures.find(location);
|
if (m_textures.size() + 1 >= getMaxTextureUnits())
|
||||||
if (it == m_textures.end())
|
|
||||||
{
|
{
|
||||||
// New entry, make sure there are enough texture units
|
err() << "Impossible to use texture " << std::quoted(name)
|
||||||
if (m_textures.size() + 1 >= getMaxTextureUnits())
|
<< " for shader: all available texture units are used" << std::endl;
|
||||||
{
|
return;
|
||||||
err() << "Impossible to use texture " << std::quoted(name)
|
}
|
||||||
<< " for shader: all available texture units are used" << std::endl;
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
m_textures[location] = &texture;
|
m_textures[location] = &texture;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
// Location already used, just replace the texture
|
// Location already used, just replace the texture
|
||||||
it->second = &texture;
|
it->second = &texture;
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -726,13 +685,13 @@ void Shader::setUniform(const std::string& name, const Texture& texture)
|
|||||||
////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////
|
||||||
void Shader::setUniform(const std::string& name, CurrentTextureType)
|
void Shader::setUniform(const std::string& name, CurrentTextureType)
|
||||||
{
|
{
|
||||||
if (m_shaderProgram)
|
if (!m_shaderProgram)
|
||||||
{
|
return;
|
||||||
const TransientContextLock lock;
|
|
||||||
|
|
||||||
// Find the location of the variable in the shader
|
const TransientContextLock lock;
|
||||||
m_currentTexture = getUniformLocation(name);
|
|
||||||
}
|
// Find the location of the variable in the shader
|
||||||
|
m_currentTexture = getUniformLocation(name);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -1077,6 +1036,74 @@ int Shader::getUniformLocation(const std::string& name)
|
|||||||
|
|
||||||
namespace sf
|
namespace sf
|
||||||
{
|
{
|
||||||
|
////////////////////////////////////////////////////////////
|
||||||
|
Shader::Shader(const std::filesystem::path& /* filename */, Type /* type */)
|
||||||
|
{
|
||||||
|
throw std::runtime_error("Shaders are not supported with OpenGL ES 1");
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////
|
||||||
|
Shader::Shader(const std::filesystem::path& /* vertexShaderFilename */,
|
||||||
|
const std::filesystem::path& /* fragmentShaderFilename */)
|
||||||
|
{
|
||||||
|
throw std::runtime_error("Shaders are not supported with OpenGL ES 1");
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////
|
||||||
|
Shader::Shader(const std::filesystem::path& /* vertexShaderFilename */,
|
||||||
|
const std::filesystem::path& /* geometryShaderFilename */,
|
||||||
|
const std::filesystem::path& /* fragmentShaderFilename */)
|
||||||
|
{
|
||||||
|
throw std::runtime_error("Shaders are not supported with OpenGL ES 1");
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////
|
||||||
|
Shader::Shader(std::string_view /* shader */, Type /* type */)
|
||||||
|
{
|
||||||
|
throw std::runtime_error("Shaders are not supported with OpenGL ES 1");
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////
|
||||||
|
Shader::Shader(std::string_view /* vertexShader */, std::string_view /* fragmentShader */)
|
||||||
|
{
|
||||||
|
throw std::runtime_error("Shaders are not supported with OpenGL ES 1");
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////
|
||||||
|
Shader::Shader(std::string_view /* vertexShader */, std::string_view /* geometryShader */, std::string_view /* fragmentShader */)
|
||||||
|
{
|
||||||
|
throw std::runtime_error("Shaders are not supported with OpenGL ES 1");
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////
|
||||||
|
Shader::Shader(InputStream& /* stream */, Type /* type */)
|
||||||
|
{
|
||||||
|
throw std::runtime_error("Shaders are not supported with OpenGL ES 1");
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////
|
||||||
|
Shader::Shader(InputStream& /* vertexShaderStream */, InputStream& /* fragmentShaderStream */)
|
||||||
|
{
|
||||||
|
throw std::runtime_error("Shaders are not supported with OpenGL ES 1");
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////
|
||||||
|
Shader::Shader(InputStream& /* vertexShaderStream */,
|
||||||
|
InputStream& /* geometryShaderStream */,
|
||||||
|
InputStream& /* fragmentShaderStream */)
|
||||||
|
{
|
||||||
|
throw std::runtime_error("Shaders are not supported with OpenGL ES 1");
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////
|
||||||
Shader::~Shader() = default;
|
Shader::~Shader() = default;
|
||||||
|
|
||||||
@ -1159,76 +1186,6 @@ bool Shader::loadFromStream(InputStream& /* vertexShaderStream */,
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////
|
|
||||||
std::optional<Shader> Shader::createFromFile(const std::filesystem::path& /* filename */, Type /* type */)
|
|
||||||
{
|
|
||||||
return std::nullopt;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////
|
|
||||||
std::optional<Shader> Shader::createFromFile(const std::filesystem::path& /* vertexShaderFilename */,
|
|
||||||
const std::filesystem::path& /* fragmentShaderFilename */)
|
|
||||||
{
|
|
||||||
return std::nullopt;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////
|
|
||||||
std::optional<Shader> Shader::createFromFile(const std::filesystem::path& /* vertexShaderFilename */,
|
|
||||||
const std::filesystem::path& /* geometryShaderFilename */,
|
|
||||||
const std::filesystem::path& /* fragmentShaderFilename */)
|
|
||||||
{
|
|
||||||
return std::nullopt;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////
|
|
||||||
std::optional<Shader> Shader::createFromMemory(std::string_view /* shader */, Type /* type */)
|
|
||||||
{
|
|
||||||
return std::nullopt;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////
|
|
||||||
std::optional<Shader> Shader::createFromMemory(std::string_view /* vertexShader */, std::string_view /* fragmentShader */)
|
|
||||||
{
|
|
||||||
return std::nullopt;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////
|
|
||||||
std::optional<Shader> Shader::createFromMemory(std::string_view /* vertexShader */,
|
|
||||||
std::string_view /* geometryShader */,
|
|
||||||
std::string_view /* fragmentShader */)
|
|
||||||
{
|
|
||||||
return std::nullopt;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////
|
|
||||||
std::optional<Shader> Shader::createFromStream(InputStream& /* stream */, Type /* type */)
|
|
||||||
{
|
|
||||||
return std::nullopt;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////
|
|
||||||
std::optional<Shader> Shader::createFromStream(InputStream& /* vertexShaderStream */, InputStream& /* fragmentShaderStream */)
|
|
||||||
{
|
|
||||||
return std::nullopt;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////
|
|
||||||
std::optional<Shader> Shader::createFromStream(InputStream& /* vertexShaderStream */,
|
|
||||||
InputStream& /* geometryShaderStream */,
|
|
||||||
InputStream& /* fragmentShaderStream */)
|
|
||||||
{
|
|
||||||
return std::nullopt;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////
|
||||||
void Shader::setUniform(const std::string& /* name */, float)
|
void Shader::setUniform(const std::string& /* name */, float)
|
||||||
{
|
{
|
||||||
|
@ -71,6 +71,78 @@ Texture::Texture() : m_cacheId(TextureImpl::getUniqueId())
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////
|
||||||
|
Texture::Texture(const std::filesystem::path& filename, bool sRgb) : Texture()
|
||||||
|
{
|
||||||
|
if (!loadFromFile(filename, sRgb))
|
||||||
|
throw std::runtime_error("Failed to load texture from file");
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////
|
||||||
|
Texture::Texture(const std::filesystem::path& filename, bool sRgb, const IntRect& area) : Texture()
|
||||||
|
{
|
||||||
|
if (!loadFromFile(filename, sRgb, area))
|
||||||
|
throw std::runtime_error("Failed to load texture from file");
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////
|
||||||
|
Texture::Texture(const void* data, std::size_t size, bool sRgb) : Texture()
|
||||||
|
{
|
||||||
|
if (!loadFromMemory(data, size, sRgb))
|
||||||
|
throw std::runtime_error("Failed to load texture from memory");
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////
|
||||||
|
Texture::Texture(const void* data, std::size_t size, bool sRgb, const IntRect& area) : Texture()
|
||||||
|
{
|
||||||
|
if (!loadFromMemory(data, size, sRgb, area))
|
||||||
|
throw std::runtime_error("Failed to load texture from memory");
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////
|
||||||
|
Texture::Texture(InputStream& stream, bool sRgb) : Texture()
|
||||||
|
{
|
||||||
|
if (!loadFromStream(stream, sRgb))
|
||||||
|
throw std::runtime_error("Failed to load texture from stream");
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////
|
||||||
|
Texture::Texture(InputStream& stream, bool sRgb, const IntRect& area) : Texture()
|
||||||
|
{
|
||||||
|
if (!loadFromStream(stream, sRgb, area))
|
||||||
|
throw std::runtime_error("Failed to load texture from stream");
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////
|
||||||
|
Texture::Texture(const Image& image, bool sRgb) : Texture()
|
||||||
|
{
|
||||||
|
if (!loadFromImage(image, sRgb))
|
||||||
|
throw std::runtime_error("Failed to load texture from image");
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////
|
||||||
|
Texture::Texture(const Image& image, bool sRgb, const IntRect& area) : Texture()
|
||||||
|
{
|
||||||
|
if (!loadFromImage(image, sRgb, area))
|
||||||
|
throw std::runtime_error("Failed to load texture from image");
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////
|
||||||
|
Texture::Texture(Vector2u size, bool sRgb) : Texture()
|
||||||
|
{
|
||||||
|
if (!resize(size, sRgb))
|
||||||
|
throw std::runtime_error("Failed to create texture");
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////
|
||||||
Texture::Texture(const Texture& copy) :
|
Texture::Texture(const Texture& copy) :
|
||||||
GlResource(copy),
|
GlResource(copy),
|
||||||
@ -361,66 +433,6 @@ bool Texture::loadFromImage(const Image& image, bool sRgb, const IntRect& area)
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////
|
|
||||||
std::optional<Texture> Texture::create(Vector2u size, bool sRgb)
|
|
||||||
{
|
|
||||||
auto texture = std::make_optional<Texture>();
|
|
||||||
|
|
||||||
if (!texture->resize(size, sRgb))
|
|
||||||
return std::nullopt;
|
|
||||||
|
|
||||||
return texture;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////
|
|
||||||
std::optional<Texture> Texture::createFromFile(const std::filesystem::path& filename, bool sRgb, const IntRect& area)
|
|
||||||
{
|
|
||||||
auto texture = std::make_optional<Texture>();
|
|
||||||
|
|
||||||
if (!texture->loadFromFile(filename, sRgb, area))
|
|
||||||
return std::nullopt;
|
|
||||||
|
|
||||||
return texture;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////
|
|
||||||
std::optional<Texture> Texture::createFromMemory(const void* data, std::size_t size, bool sRgb, const IntRect& area)
|
|
||||||
{
|
|
||||||
auto texture = std::make_optional<Texture>();
|
|
||||||
|
|
||||||
if (!texture->loadFromMemory(data, size, sRgb, area))
|
|
||||||
return std::nullopt;
|
|
||||||
|
|
||||||
return texture;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////
|
|
||||||
std::optional<Texture> Texture::createFromStream(InputStream& stream, bool sRgb, const IntRect& area)
|
|
||||||
{
|
|
||||||
auto texture = std::make_optional<Texture>();
|
|
||||||
|
|
||||||
if (!texture->loadFromStream(stream, sRgb, area))
|
|
||||||
return std::nullopt;
|
|
||||||
|
|
||||||
return texture;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////
|
|
||||||
std::optional<Texture> Texture::createFromImage(const Image& image, bool sRgb, const IntRect& area)
|
|
||||||
{
|
|
||||||
auto texture = std::make_optional<Texture>();
|
|
||||||
|
|
||||||
if (!texture->loadFromImage(image, sRgb, area))
|
|
||||||
return std::nullopt;
|
|
||||||
|
|
||||||
return texture;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////
|
||||||
Vector2u Texture::getSize() const
|
Vector2u Texture::getSize() const
|
||||||
{
|
{
|
||||||
|
@ -47,6 +47,14 @@ void FileInputStream::FileCloser::operator()(std::FILE* file)
|
|||||||
FileInputStream::FileInputStream() = default;
|
FileInputStream::FileInputStream() = default;
|
||||||
|
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////
|
||||||
|
FileInputStream::FileInputStream(const std::filesystem::path& filename)
|
||||||
|
{
|
||||||
|
if (!open(filename))
|
||||||
|
throw std::runtime_error("Failed to open file input stream");
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////
|
||||||
FileInputStream::~FileInputStream() = default;
|
FileInputStream::~FileInputStream() = default;
|
||||||
|
|
||||||
@ -78,18 +86,6 @@ bool FileInputStream::open(const std::filesystem::path& filename)
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////
|
|
||||||
std::optional<FileInputStream> FileInputStream::create(const std::filesystem::path& filename)
|
|
||||||
{
|
|
||||||
auto fileInputStream = std::make_optional<FileInputStream>();
|
|
||||||
|
|
||||||
if (!fileInputStream->open(filename))
|
|
||||||
return std::nullopt;
|
|
||||||
|
|
||||||
return fileInputStream;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////
|
||||||
std::optional<std::size_t> FileInputStream::read(void* data, std::size_t size)
|
std::optional<std::size_t> FileInputStream::read(void* data, std::size_t size)
|
||||||
{
|
{
|
||||||
|
@ -35,18 +35,10 @@
|
|||||||
namespace sf
|
namespace sf
|
||||||
{
|
{
|
||||||
////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////
|
||||||
MemoryInputStream::MemoryInputStream(const void* data, std::size_t sizeInBytes)
|
MemoryInputStream::MemoryInputStream(const void* data, std::size_t sizeInBytes) :
|
||||||
|
m_data(static_cast<const std::byte*>(data)),
|
||||||
|
m_size(sizeInBytes)
|
||||||
{
|
{
|
||||||
open(data, sizeInBytes);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////
|
|
||||||
void MemoryInputStream::open(const void* data, std::size_t sizeInBytes)
|
|
||||||
{
|
|
||||||
m_data = static_cast<const std::byte*>(data);
|
|
||||||
m_size = sizeInBytes;
|
|
||||||
m_offset = 0;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -43,6 +43,25 @@ Cursor::Cursor() : m_impl(std::make_unique<priv::CursorImpl>())
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////
|
||||||
|
Cursor::Cursor(const std::uint8_t* pixels, Vector2u size, Vector2u hotspot) : Cursor()
|
||||||
|
{
|
||||||
|
if ((pixels == nullptr) || (size.x == 0) || (size.y == 0))
|
||||||
|
throw std::runtime_error("Failed to create cursor from pixels (invalid arguments)");
|
||||||
|
|
||||||
|
if (!m_impl->loadFromPixels(pixels, size, hotspot))
|
||||||
|
throw std::runtime_error("Failed to create cursor from pixels");
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////
|
||||||
|
Cursor::Cursor(Type type) : Cursor()
|
||||||
|
{
|
||||||
|
if (!m_impl->loadFromSystem(type))
|
||||||
|
throw std::runtime_error("Failed to create cursor from type");
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////
|
||||||
Cursor::~Cursor() = default;
|
Cursor::~Cursor() = default;
|
||||||
|
|
||||||
|
@ -23,13 +23,131 @@ TEST_CASE("[Audio] sf::InputSoundFile")
|
|||||||
|
|
||||||
SECTION("Construction")
|
SECTION("Construction")
|
||||||
{
|
{
|
||||||
const sf::InputSoundFile inputSoundFile;
|
SECTION("Default constructor")
|
||||||
CHECK(inputSoundFile.getSampleCount() == 0);
|
{
|
||||||
CHECK(inputSoundFile.getChannelCount() == 0);
|
const sf::InputSoundFile inputSoundFile;
|
||||||
CHECK(inputSoundFile.getSampleRate() == 0);
|
CHECK(inputSoundFile.getSampleCount() == 0);
|
||||||
CHECK(inputSoundFile.getDuration() == sf::Time::Zero);
|
CHECK(inputSoundFile.getChannelCount() == 0);
|
||||||
CHECK(inputSoundFile.getTimeOffset() == sf::Time::Zero);
|
CHECK(inputSoundFile.getSampleRate() == 0);
|
||||||
CHECK(inputSoundFile.getSampleOffset() == 0);
|
CHECK(inputSoundFile.getDuration() == sf::Time::Zero);
|
||||||
|
CHECK(inputSoundFile.getTimeOffset() == sf::Time::Zero);
|
||||||
|
CHECK(inputSoundFile.getSampleOffset() == 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
SECTION("Invalid file")
|
||||||
|
{
|
||||||
|
CHECK_THROWS_AS(sf::InputSoundFile("does/not/exist.wav"), std::runtime_error);
|
||||||
|
}
|
||||||
|
|
||||||
|
SECTION("Valid file")
|
||||||
|
{
|
||||||
|
SECTION("flac")
|
||||||
|
{
|
||||||
|
const sf::InputSoundFile inputSoundFile("Audio/ding.flac");
|
||||||
|
CHECK(inputSoundFile.getSampleCount() == 87'798);
|
||||||
|
CHECK(inputSoundFile.getChannelCount() == 1);
|
||||||
|
CHECK(inputSoundFile.getSampleRate() == 44'100);
|
||||||
|
CHECK(inputSoundFile.getDuration() == sf::microseconds(1'990'884));
|
||||||
|
CHECK(inputSoundFile.getTimeOffset() == sf::Time::Zero);
|
||||||
|
CHECK(inputSoundFile.getSampleOffset() == 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
SECTION("mp3")
|
||||||
|
{
|
||||||
|
const sf::InputSoundFile inputSoundFile("Audio/ding.mp3");
|
||||||
|
CHECK(inputSoundFile.getSampleCount() == 87'798);
|
||||||
|
CHECK(inputSoundFile.getChannelCount() == 1);
|
||||||
|
CHECK(inputSoundFile.getSampleRate() == 44'100);
|
||||||
|
CHECK(inputSoundFile.getDuration() == sf::microseconds(1'990'884));
|
||||||
|
CHECK(inputSoundFile.getTimeOffset() == sf::Time::Zero);
|
||||||
|
CHECK(inputSoundFile.getSampleOffset() == 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
SECTION("ogg")
|
||||||
|
{
|
||||||
|
const sf::InputSoundFile inputSoundFile("Audio/doodle_pop.ogg");
|
||||||
|
CHECK(inputSoundFile.getSampleCount() == 2'116'992);
|
||||||
|
CHECK(inputSoundFile.getChannelCount() == 2);
|
||||||
|
CHECK(inputSoundFile.getSampleRate() == 44'100);
|
||||||
|
CHECK(inputSoundFile.getDuration() == sf::microseconds(24'002'176));
|
||||||
|
CHECK(inputSoundFile.getTimeOffset() == sf::Time::Zero);
|
||||||
|
CHECK(inputSoundFile.getSampleOffset() == 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
SECTION("wav")
|
||||||
|
{
|
||||||
|
const sf::InputSoundFile inputSoundFile("Audio/killdeer.wav");
|
||||||
|
CHECK(inputSoundFile.getSampleCount() == 112'941);
|
||||||
|
CHECK(inputSoundFile.getChannelCount() == 1);
|
||||||
|
CHECK(inputSoundFile.getSampleRate() == 22'050);
|
||||||
|
CHECK(inputSoundFile.getDuration() == sf::microseconds(5'122'040));
|
||||||
|
CHECK(inputSoundFile.getTimeOffset() == sf::Time::Zero);
|
||||||
|
CHECK(inputSoundFile.getSampleOffset() == 0);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
SECTION("Memory")
|
||||||
|
{
|
||||||
|
const auto memory = loadIntoMemory("Audio/killdeer.wav");
|
||||||
|
const sf::InputSoundFile inputSoundFile(memory.data(), memory.size());
|
||||||
|
CHECK(inputSoundFile.getSampleCount() == 112'941);
|
||||||
|
CHECK(inputSoundFile.getChannelCount() == 1);
|
||||||
|
CHECK(inputSoundFile.getSampleRate() == 22'050);
|
||||||
|
CHECK(inputSoundFile.getDuration() == sf::microseconds(5'122'040));
|
||||||
|
CHECK(inputSoundFile.getTimeOffset() == sf::Time::Zero);
|
||||||
|
CHECK(inputSoundFile.getSampleOffset() == 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
SECTION("Stream")
|
||||||
|
{
|
||||||
|
SECTION("flac")
|
||||||
|
{
|
||||||
|
sf::FileInputStream stream("Audio/ding.flac");
|
||||||
|
const sf::InputSoundFile inputSoundFile(stream);
|
||||||
|
CHECK(inputSoundFile.getSampleCount() == 87'798);
|
||||||
|
CHECK(inputSoundFile.getChannelCount() == 1);
|
||||||
|
CHECK(inputSoundFile.getSampleRate() == 44'100);
|
||||||
|
CHECK(inputSoundFile.getDuration() == sf::microseconds(1'990'884));
|
||||||
|
CHECK(inputSoundFile.getTimeOffset() == sf::Time::Zero);
|
||||||
|
CHECK(inputSoundFile.getSampleOffset() == 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
SECTION("mp3")
|
||||||
|
{
|
||||||
|
sf::FileInputStream stream("Audio/ding.mp3");
|
||||||
|
const sf::InputSoundFile inputSoundFile(stream);
|
||||||
|
CHECK(inputSoundFile.getSampleCount() == 87'798);
|
||||||
|
CHECK(inputSoundFile.getChannelCount() == 1);
|
||||||
|
CHECK(inputSoundFile.getSampleRate() == 44'100);
|
||||||
|
CHECK(inputSoundFile.getDuration() == sf::microseconds(1'990'884));
|
||||||
|
CHECK(inputSoundFile.getTimeOffset() == sf::Time::Zero);
|
||||||
|
CHECK(inputSoundFile.getSampleOffset() == 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
SECTION("ogg")
|
||||||
|
{
|
||||||
|
sf::FileInputStream stream("Audio/doodle_pop.ogg");
|
||||||
|
const sf::InputSoundFile inputSoundFile(stream);
|
||||||
|
CHECK(inputSoundFile.getSampleCount() == 2'116'992);
|
||||||
|
CHECK(inputSoundFile.getChannelCount() == 2);
|
||||||
|
CHECK(inputSoundFile.getSampleRate() == 44'100);
|
||||||
|
CHECK(inputSoundFile.getDuration() == sf::microseconds(24'002'176));
|
||||||
|
CHECK(inputSoundFile.getTimeOffset() == sf::Time::Zero);
|
||||||
|
CHECK(inputSoundFile.getSampleOffset() == 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
SECTION("wav")
|
||||||
|
{
|
||||||
|
sf::FileInputStream stream("Audio/killdeer.wav");
|
||||||
|
const sf::InputSoundFile inputSoundFile(stream);
|
||||||
|
CHECK(inputSoundFile.getSampleCount() == 112'941);
|
||||||
|
CHECK(inputSoundFile.getChannelCount() == 1);
|
||||||
|
CHECK(inputSoundFile.getSampleRate() == 22'050);
|
||||||
|
CHECK(inputSoundFile.getDuration() == sf::microseconds(5'122'040));
|
||||||
|
CHECK(inputSoundFile.getTimeOffset() == sf::Time::Zero);
|
||||||
|
CHECK(inputSoundFile.getSampleOffset() == 0);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
SECTION("openFromFile()")
|
SECTION("openFromFile()")
|
||||||
@ -164,129 +282,11 @@ TEST_CASE("[Audio] sf::InputSoundFile")
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
SECTION("createFromFile()")
|
|
||||||
{
|
|
||||||
SECTION("Invalid file")
|
|
||||||
{
|
|
||||||
CHECK(!sf::InputSoundFile::createFromFile("does/not/exist.wav"));
|
|
||||||
}
|
|
||||||
|
|
||||||
SECTION("Valid file")
|
|
||||||
{
|
|
||||||
SECTION("flac")
|
|
||||||
{
|
|
||||||
const auto inputSoundFile = sf::InputSoundFile::createFromFile("Audio/ding.flac").value();
|
|
||||||
CHECK(inputSoundFile.getSampleCount() == 87'798);
|
|
||||||
CHECK(inputSoundFile.getChannelCount() == 1);
|
|
||||||
CHECK(inputSoundFile.getSampleRate() == 44'100);
|
|
||||||
CHECK(inputSoundFile.getDuration() == sf::microseconds(1'990'884));
|
|
||||||
CHECK(inputSoundFile.getTimeOffset() == sf::Time::Zero);
|
|
||||||
CHECK(inputSoundFile.getSampleOffset() == 0);
|
|
||||||
}
|
|
||||||
|
|
||||||
SECTION("mp3")
|
|
||||||
{
|
|
||||||
const auto inputSoundFile = sf::InputSoundFile::createFromFile("Audio/ding.mp3").value();
|
|
||||||
CHECK(inputSoundFile.getSampleCount() == 87'798);
|
|
||||||
CHECK(inputSoundFile.getChannelCount() == 1);
|
|
||||||
CHECK(inputSoundFile.getSampleRate() == 44'100);
|
|
||||||
CHECK(inputSoundFile.getDuration() == sf::microseconds(1'990'884));
|
|
||||||
CHECK(inputSoundFile.getTimeOffset() == sf::Time::Zero);
|
|
||||||
CHECK(inputSoundFile.getSampleOffset() == 0);
|
|
||||||
}
|
|
||||||
|
|
||||||
SECTION("ogg")
|
|
||||||
{
|
|
||||||
const auto inputSoundFile = sf::InputSoundFile::createFromFile("Audio/doodle_pop.ogg").value();
|
|
||||||
CHECK(inputSoundFile.getSampleCount() == 2'116'992);
|
|
||||||
CHECK(inputSoundFile.getChannelCount() == 2);
|
|
||||||
CHECK(inputSoundFile.getSampleRate() == 44'100);
|
|
||||||
CHECK(inputSoundFile.getDuration() == sf::microseconds(24'002'176));
|
|
||||||
CHECK(inputSoundFile.getTimeOffset() == sf::Time::Zero);
|
|
||||||
CHECK(inputSoundFile.getSampleOffset() == 0);
|
|
||||||
}
|
|
||||||
|
|
||||||
SECTION("wav")
|
|
||||||
{
|
|
||||||
const auto inputSoundFile = sf::InputSoundFile::createFromFile("Audio/killdeer.wav").value();
|
|
||||||
CHECK(inputSoundFile.getSampleCount() == 112'941);
|
|
||||||
CHECK(inputSoundFile.getChannelCount() == 1);
|
|
||||||
CHECK(inputSoundFile.getSampleRate() == 22'050);
|
|
||||||
CHECK(inputSoundFile.getDuration() == sf::microseconds(5'122'040));
|
|
||||||
CHECK(inputSoundFile.getTimeOffset() == sf::Time::Zero);
|
|
||||||
CHECK(inputSoundFile.getSampleOffset() == 0);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
SECTION("createFromMemory()")
|
|
||||||
{
|
|
||||||
const auto memory = loadIntoMemory("Audio/killdeer.wav");
|
|
||||||
const auto inputSoundFile = sf::InputSoundFile::createFromMemory(memory.data(), memory.size()).value();
|
|
||||||
CHECK(inputSoundFile.getSampleCount() == 112'941);
|
|
||||||
CHECK(inputSoundFile.getChannelCount() == 1);
|
|
||||||
CHECK(inputSoundFile.getSampleRate() == 22'050);
|
|
||||||
CHECK(inputSoundFile.getDuration() == sf::microseconds(5'122'040));
|
|
||||||
CHECK(inputSoundFile.getTimeOffset() == sf::Time::Zero);
|
|
||||||
CHECK(inputSoundFile.getSampleOffset() == 0);
|
|
||||||
}
|
|
||||||
|
|
||||||
SECTION("createFromStream()")
|
|
||||||
{
|
|
||||||
SECTION("flac")
|
|
||||||
{
|
|
||||||
auto stream = sf::FileInputStream::create("Audio/ding.flac").value();
|
|
||||||
const auto inputSoundFile = sf::InputSoundFile::createFromStream(stream).value();
|
|
||||||
CHECK(inputSoundFile.getSampleCount() == 87'798);
|
|
||||||
CHECK(inputSoundFile.getChannelCount() == 1);
|
|
||||||
CHECK(inputSoundFile.getSampleRate() == 44'100);
|
|
||||||
CHECK(inputSoundFile.getDuration() == sf::microseconds(1'990'884));
|
|
||||||
CHECK(inputSoundFile.getTimeOffset() == sf::Time::Zero);
|
|
||||||
CHECK(inputSoundFile.getSampleOffset() == 0);
|
|
||||||
}
|
|
||||||
|
|
||||||
SECTION("mp3")
|
|
||||||
{
|
|
||||||
auto stream = sf::FileInputStream::create("Audio/ding.mp3").value();
|
|
||||||
const auto inputSoundFile = sf::InputSoundFile::createFromStream(stream).value();
|
|
||||||
CHECK(inputSoundFile.getSampleCount() == 87'798);
|
|
||||||
CHECK(inputSoundFile.getChannelCount() == 1);
|
|
||||||
CHECK(inputSoundFile.getSampleRate() == 44'100);
|
|
||||||
CHECK(inputSoundFile.getDuration() == sf::microseconds(1'990'884));
|
|
||||||
CHECK(inputSoundFile.getTimeOffset() == sf::Time::Zero);
|
|
||||||
CHECK(inputSoundFile.getSampleOffset() == 0);
|
|
||||||
}
|
|
||||||
|
|
||||||
SECTION("ogg")
|
|
||||||
{
|
|
||||||
auto stream = sf::FileInputStream::create("Audio/doodle_pop.ogg").value();
|
|
||||||
const auto inputSoundFile = sf::InputSoundFile::createFromStream(stream).value();
|
|
||||||
CHECK(inputSoundFile.getSampleCount() == 2'116'992);
|
|
||||||
CHECK(inputSoundFile.getChannelCount() == 2);
|
|
||||||
CHECK(inputSoundFile.getSampleRate() == 44'100);
|
|
||||||
CHECK(inputSoundFile.getDuration() == sf::microseconds(24'002'176));
|
|
||||||
CHECK(inputSoundFile.getTimeOffset() == sf::Time::Zero);
|
|
||||||
CHECK(inputSoundFile.getSampleOffset() == 0);
|
|
||||||
}
|
|
||||||
|
|
||||||
SECTION("wav")
|
|
||||||
{
|
|
||||||
auto stream = sf::FileInputStream::create("Audio/killdeer.wav").value();
|
|
||||||
const auto inputSoundFile = sf::InputSoundFile::createFromStream(stream).value();
|
|
||||||
CHECK(inputSoundFile.getSampleCount() == 112'941);
|
|
||||||
CHECK(inputSoundFile.getChannelCount() == 1);
|
|
||||||
CHECK(inputSoundFile.getSampleRate() == 22'050);
|
|
||||||
CHECK(inputSoundFile.getDuration() == sf::microseconds(5'122'040));
|
|
||||||
CHECK(inputSoundFile.getTimeOffset() == sf::Time::Zero);
|
|
||||||
CHECK(inputSoundFile.getSampleOffset() == 0);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
SECTION("seek(std::uint64_t)")
|
SECTION("seek(std::uint64_t)")
|
||||||
{
|
{
|
||||||
SECTION("flac")
|
SECTION("flac")
|
||||||
{
|
{
|
||||||
auto inputSoundFile = sf::InputSoundFile::createFromFile("Audio/ding.flac").value();
|
sf::InputSoundFile inputSoundFile("Audio/ding.flac");
|
||||||
inputSoundFile.seek(1'000);
|
inputSoundFile.seek(1'000);
|
||||||
CHECK(inputSoundFile.getTimeOffset() == sf::microseconds(22'675));
|
CHECK(inputSoundFile.getTimeOffset() == sf::microseconds(22'675));
|
||||||
CHECK(inputSoundFile.getSampleOffset() == 1'000);
|
CHECK(inputSoundFile.getSampleOffset() == 1'000);
|
||||||
@ -294,7 +294,7 @@ TEST_CASE("[Audio] sf::InputSoundFile")
|
|||||||
|
|
||||||
SECTION("mp3")
|
SECTION("mp3")
|
||||||
{
|
{
|
||||||
auto inputSoundFile = sf::InputSoundFile::createFromFile("Audio/ding.mp3").value();
|
sf::InputSoundFile inputSoundFile("Audio/ding.mp3");
|
||||||
inputSoundFile.seek(1'000);
|
inputSoundFile.seek(1'000);
|
||||||
CHECK(inputSoundFile.getTimeOffset() == sf::microseconds(22'675));
|
CHECK(inputSoundFile.getTimeOffset() == sf::microseconds(22'675));
|
||||||
CHECK(inputSoundFile.getSampleOffset() == 1'000);
|
CHECK(inputSoundFile.getSampleOffset() == 1'000);
|
||||||
@ -302,7 +302,7 @@ TEST_CASE("[Audio] sf::InputSoundFile")
|
|||||||
|
|
||||||
SECTION("ogg")
|
SECTION("ogg")
|
||||||
{
|
{
|
||||||
auto inputSoundFile = sf::InputSoundFile::createFromFile("Audio/doodle_pop.ogg").value();
|
sf::InputSoundFile inputSoundFile("Audio/doodle_pop.ogg");
|
||||||
inputSoundFile.seek(1'000);
|
inputSoundFile.seek(1'000);
|
||||||
CHECK(inputSoundFile.getTimeOffset() == sf::microseconds(11'337));
|
CHECK(inputSoundFile.getTimeOffset() == sf::microseconds(11'337));
|
||||||
CHECK(inputSoundFile.getSampleOffset() == 1'000);
|
CHECK(inputSoundFile.getSampleOffset() == 1'000);
|
||||||
@ -310,7 +310,7 @@ TEST_CASE("[Audio] sf::InputSoundFile")
|
|||||||
|
|
||||||
SECTION("wav")
|
SECTION("wav")
|
||||||
{
|
{
|
||||||
auto inputSoundFile = sf::InputSoundFile::createFromFile("Audio/killdeer.wav").value();
|
sf::InputSoundFile inputSoundFile("Audio/killdeer.wav");
|
||||||
inputSoundFile.seek(1'000);
|
inputSoundFile.seek(1'000);
|
||||||
CHECK(inputSoundFile.getTimeOffset() == sf::microseconds(45'351));
|
CHECK(inputSoundFile.getTimeOffset() == sf::microseconds(45'351));
|
||||||
CHECK(inputSoundFile.getSampleOffset() == 1'000);
|
CHECK(inputSoundFile.getSampleOffset() == 1'000);
|
||||||
@ -319,7 +319,7 @@ TEST_CASE("[Audio] sf::InputSoundFile")
|
|||||||
|
|
||||||
SECTION("seek(Time)")
|
SECTION("seek(Time)")
|
||||||
{
|
{
|
||||||
auto inputSoundFile = sf::InputSoundFile::createFromFile("Audio/ding.flac").value();
|
sf::InputSoundFile inputSoundFile("Audio/ding.flac");
|
||||||
inputSoundFile.seek(sf::milliseconds(100));
|
inputSoundFile.seek(sf::milliseconds(100));
|
||||||
CHECK(inputSoundFile.getSampleCount() == 87'798);
|
CHECK(inputSoundFile.getSampleCount() == 87'798);
|
||||||
CHECK(inputSoundFile.getChannelCount() == 1);
|
CHECK(inputSoundFile.getChannelCount() == 1);
|
||||||
@ -331,7 +331,7 @@ TEST_CASE("[Audio] sf::InputSoundFile")
|
|||||||
|
|
||||||
SECTION("read()")
|
SECTION("read()")
|
||||||
{
|
{
|
||||||
auto inputSoundFile = sf::InputSoundFile::createFromFile("Audio/ding.flac").value();
|
sf::InputSoundFile inputSoundFile("Audio/ding.flac");
|
||||||
|
|
||||||
SECTION("Null address")
|
SECTION("Null address")
|
||||||
{
|
{
|
||||||
@ -349,7 +349,7 @@ TEST_CASE("[Audio] sf::InputSoundFile")
|
|||||||
{
|
{
|
||||||
SECTION("flac")
|
SECTION("flac")
|
||||||
{
|
{
|
||||||
inputSoundFile = sf::InputSoundFile::createFromFile("Audio/ding.flac").value();
|
inputSoundFile = sf::InputSoundFile("Audio/ding.flac");
|
||||||
CHECK(inputSoundFile.read(samples.data(), samples.size()) == 4);
|
CHECK(inputSoundFile.read(samples.data(), samples.size()) == 4);
|
||||||
CHECK(samples == std::array<std::int16_t, 4>{0, 1, -1, 4});
|
CHECK(samples == std::array<std::int16_t, 4>{0, 1, -1, 4});
|
||||||
CHECK(inputSoundFile.read(samples.data(), samples.size()) == 4);
|
CHECK(inputSoundFile.read(samples.data(), samples.size()) == 4);
|
||||||
@ -358,7 +358,7 @@ TEST_CASE("[Audio] sf::InputSoundFile")
|
|||||||
|
|
||||||
SECTION("mp3")
|
SECTION("mp3")
|
||||||
{
|
{
|
||||||
inputSoundFile = sf::InputSoundFile::createFromFile("Audio/ding.mp3").value();
|
inputSoundFile = sf::InputSoundFile("Audio/ding.mp3");
|
||||||
CHECK(inputSoundFile.read(samples.data(), samples.size()) == 4);
|
CHECK(inputSoundFile.read(samples.data(), samples.size()) == 4);
|
||||||
CHECK(samples == std::array<std::int16_t, 4>{0, -2, 0, 2});
|
CHECK(samples == std::array<std::int16_t, 4>{0, -2, 0, 2});
|
||||||
CHECK(inputSoundFile.read(samples.data(), samples.size()) == 4);
|
CHECK(inputSoundFile.read(samples.data(), samples.size()) == 4);
|
||||||
@ -367,7 +367,7 @@ TEST_CASE("[Audio] sf::InputSoundFile")
|
|||||||
|
|
||||||
SECTION("ogg")
|
SECTION("ogg")
|
||||||
{
|
{
|
||||||
inputSoundFile = sf::InputSoundFile::createFromFile("Audio/doodle_pop.ogg").value();
|
inputSoundFile = sf::InputSoundFile("Audio/doodle_pop.ogg");
|
||||||
CHECK(inputSoundFile.read(samples.data(), samples.size()) == 4);
|
CHECK(inputSoundFile.read(samples.data(), samples.size()) == 4);
|
||||||
CHECK(samples == std::array<std::int16_t, 4>{-827, -985, -1168, -1319});
|
CHECK(samples == std::array<std::int16_t, 4>{-827, -985, -1168, -1319});
|
||||||
CHECK(inputSoundFile.read(samples.data(), samples.size()) == 4);
|
CHECK(inputSoundFile.read(samples.data(), samples.size()) == 4);
|
||||||
@ -383,7 +383,7 @@ TEST_CASE("[Audio] sf::InputSoundFile")
|
|||||||
|
|
||||||
SECTION("close()")
|
SECTION("close()")
|
||||||
{
|
{
|
||||||
auto inputSoundFile = sf::InputSoundFile::createFromFile("Audio/ding.flac").value();
|
sf::InputSoundFile inputSoundFile("Audio/ding.flac");
|
||||||
inputSoundFile.close();
|
inputSoundFile.close();
|
||||||
CHECK(inputSoundFile.getSampleCount() == 0);
|
CHECK(inputSoundFile.getSampleCount() == 0);
|
||||||
CHECK(inputSoundFile.getChannelCount() == 0);
|
CHECK(inputSoundFile.getChannelCount() == 0);
|
||||||
|
@ -32,18 +32,84 @@ TEST_CASE("[Audio] sf::Music", runAudioDeviceTests())
|
|||||||
CHECK(timeSpan.length == sf::Time::Zero);
|
CHECK(timeSpan.length == sf::Time::Zero);
|
||||||
}
|
}
|
||||||
|
|
||||||
SECTION("Construction")
|
SECTION("Constructor")
|
||||||
{
|
{
|
||||||
const sf::Music music;
|
SECTION("Default constructor")
|
||||||
CHECK(music.getDuration() == sf::Time::Zero);
|
{
|
||||||
const auto [offset, length] = music.getLoopPoints();
|
const sf::Music music;
|
||||||
CHECK(offset == sf::Time::Zero);
|
CHECK(music.getDuration() == sf::Time::Zero);
|
||||||
CHECK(length == sf::Time::Zero);
|
const auto [offset, length] = music.getLoopPoints();
|
||||||
CHECK(music.getChannelCount() == 0);
|
CHECK(offset == sf::Time::Zero);
|
||||||
CHECK(music.getSampleRate() == 0);
|
CHECK(length == sf::Time::Zero);
|
||||||
CHECK(music.getStatus() == sf::Music::Status::Stopped);
|
CHECK(music.getChannelCount() == 0);
|
||||||
CHECK(music.getPlayingOffset() == sf::Time::Zero);
|
CHECK(music.getSampleRate() == 0);
|
||||||
CHECK(!music.getLoop());
|
CHECK(music.getStatus() == sf::Music::Status::Stopped);
|
||||||
|
CHECK(music.getPlayingOffset() == sf::Time::Zero);
|
||||||
|
CHECK(!music.getLoop());
|
||||||
|
}
|
||||||
|
|
||||||
|
SECTION("File")
|
||||||
|
{
|
||||||
|
SECTION("Invalid file")
|
||||||
|
{
|
||||||
|
CHECK_THROWS_AS(sf::Music("does/not/exist.wav"), std::runtime_error);
|
||||||
|
}
|
||||||
|
|
||||||
|
SECTION("Valid file")
|
||||||
|
{
|
||||||
|
const sf::Music music("Audio/ding.mp3");
|
||||||
|
CHECK(music.getDuration() == sf::microseconds(1990884));
|
||||||
|
const auto [offset, length] = music.getLoopPoints();
|
||||||
|
CHECK(offset == sf::Time::Zero);
|
||||||
|
CHECK(length == sf::microseconds(1990884));
|
||||||
|
CHECK(music.getChannelCount() == 1);
|
||||||
|
CHECK(music.getSampleRate() == 44100);
|
||||||
|
CHECK(music.getStatus() == sf::Music::Status::Stopped);
|
||||||
|
CHECK(music.getPlayingOffset() == sf::Time::Zero);
|
||||||
|
CHECK(!music.getLoop());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
SECTION("Memory")
|
||||||
|
{
|
||||||
|
std::vector<std::byte> memory(10, std::byte{0xCA});
|
||||||
|
|
||||||
|
SECTION("Invalid buffer")
|
||||||
|
{
|
||||||
|
CHECK_THROWS_AS(sf::Music(memory.data(), memory.size()), std::runtime_error);
|
||||||
|
}
|
||||||
|
|
||||||
|
SECTION("Valid buffer")
|
||||||
|
{
|
||||||
|
memory = loadIntoMemory("Audio/ding.flac");
|
||||||
|
|
||||||
|
const sf::Music music(memory.data(), memory.size());
|
||||||
|
CHECK(music.getDuration() == sf::microseconds(1990884));
|
||||||
|
const auto [offset, length] = music.getLoopPoints();
|
||||||
|
CHECK(offset == sf::Time::Zero);
|
||||||
|
CHECK(length == sf::microseconds(1990884));
|
||||||
|
CHECK(music.getChannelCount() == 1);
|
||||||
|
CHECK(music.getSampleRate() == 44100);
|
||||||
|
CHECK(music.getStatus() == sf::Music::Status::Stopped);
|
||||||
|
CHECK(music.getPlayingOffset() == sf::Time::Zero);
|
||||||
|
CHECK(!music.getLoop());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
SECTION("Stream")
|
||||||
|
{
|
||||||
|
sf::FileInputStream stream("Audio/doodle_pop.ogg");
|
||||||
|
const sf::Music music(stream);
|
||||||
|
CHECK(music.getDuration() == sf::microseconds(24002176));
|
||||||
|
const auto [offset, length] = music.getLoopPoints();
|
||||||
|
CHECK(offset == sf::Time::Zero);
|
||||||
|
CHECK(length == sf::microseconds(24002176));
|
||||||
|
CHECK(music.getChannelCount() == 2);
|
||||||
|
CHECK(music.getSampleRate() == 44100);
|
||||||
|
CHECK(music.getStatus() == sf::Music::Status::Stopped);
|
||||||
|
CHECK(music.getPlayingOffset() == sf::Time::Zero);
|
||||||
|
CHECK(!music.getLoop());
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
SECTION("openFromFile()")
|
SECTION("openFromFile()")
|
||||||
@ -149,72 +215,9 @@ TEST_CASE("[Audio] sf::Music", runAudioDeviceTests())
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
SECTION("createFromFile()")
|
|
||||||
{
|
|
||||||
SECTION("Invalid file")
|
|
||||||
{
|
|
||||||
CHECK(!sf::Music::createFromFile("does/not/exist.wav"));
|
|
||||||
}
|
|
||||||
|
|
||||||
SECTION("Valid file")
|
|
||||||
{
|
|
||||||
const auto music = sf::Music::createFromFile("Audio/ding.mp3").value();
|
|
||||||
CHECK(music.getDuration() == sf::microseconds(1990884));
|
|
||||||
const auto [offset, length] = music.getLoopPoints();
|
|
||||||
CHECK(offset == sf::Time::Zero);
|
|
||||||
CHECK(length == sf::microseconds(1990884));
|
|
||||||
CHECK(music.getChannelCount() == 1);
|
|
||||||
CHECK(music.getSampleRate() == 44100);
|
|
||||||
CHECK(music.getStatus() == sf::Music::Status::Stopped);
|
|
||||||
CHECK(music.getPlayingOffset() == sf::Time::Zero);
|
|
||||||
CHECK(!music.getLoop());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
SECTION("createFromMemory()")
|
|
||||||
{
|
|
||||||
std::vector<std::byte> memory(10, std::byte{0xCA});
|
|
||||||
|
|
||||||
SECTION("Invalid buffer")
|
|
||||||
{
|
|
||||||
CHECK(!sf::Music::createFromMemory(memory.data(), memory.size()));
|
|
||||||
}
|
|
||||||
|
|
||||||
SECTION("Valid buffer")
|
|
||||||
{
|
|
||||||
memory = loadIntoMemory("Audio/ding.flac");
|
|
||||||
|
|
||||||
const auto music = sf::Music::createFromMemory(memory.data(), memory.size()).value();
|
|
||||||
CHECK(music.getDuration() == sf::microseconds(1990884));
|
|
||||||
const auto [offset, length] = music.getLoopPoints();
|
|
||||||
CHECK(offset == sf::Time::Zero);
|
|
||||||
CHECK(length == sf::microseconds(1990884));
|
|
||||||
CHECK(music.getChannelCount() == 1);
|
|
||||||
CHECK(music.getSampleRate() == 44100);
|
|
||||||
CHECK(music.getStatus() == sf::Music::Status::Stopped);
|
|
||||||
CHECK(music.getPlayingOffset() == sf::Time::Zero);
|
|
||||||
CHECK(!music.getLoop());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
SECTION("createFromStream()")
|
|
||||||
{
|
|
||||||
auto stream = sf::FileInputStream::create("Audio/doodle_pop.ogg").value();
|
|
||||||
const auto music = sf::Music::createFromStream(stream).value();
|
|
||||||
CHECK(music.getDuration() == sf::microseconds(24002176));
|
|
||||||
const auto [offset, length] = music.getLoopPoints();
|
|
||||||
CHECK(offset == sf::Time::Zero);
|
|
||||||
CHECK(length == sf::microseconds(24002176));
|
|
||||||
CHECK(music.getChannelCount() == 2);
|
|
||||||
CHECK(music.getSampleRate() == 44100);
|
|
||||||
CHECK(music.getStatus() == sf::Music::Status::Stopped);
|
|
||||||
CHECK(music.getPlayingOffset() == sf::Time::Zero);
|
|
||||||
CHECK(!music.getLoop());
|
|
||||||
}
|
|
||||||
|
|
||||||
SECTION("play/pause/stop")
|
SECTION("play/pause/stop")
|
||||||
{
|
{
|
||||||
auto music = sf::Music::createFromFile("Audio/ding.mp3").value();
|
sf::Music music("Audio/ding.mp3");
|
||||||
|
|
||||||
// Wait for background thread to start
|
// Wait for background thread to start
|
||||||
music.play();
|
music.play();
|
||||||
@ -237,7 +240,7 @@ TEST_CASE("[Audio] sf::Music", runAudioDeviceTests())
|
|||||||
|
|
||||||
SECTION("setLoopPoints()")
|
SECTION("setLoopPoints()")
|
||||||
{
|
{
|
||||||
auto music = sf::Music::createFromFile("Audio/killdeer.wav").value();
|
sf::Music music("Audio/killdeer.wav");
|
||||||
music.setLoopPoints({sf::seconds(1), sf::seconds(2)});
|
music.setLoopPoints({sf::seconds(1), sf::seconds(2)});
|
||||||
const auto [offset, length] = music.getLoopPoints();
|
const auto [offset, length] = music.getLoopPoints();
|
||||||
CHECK(offset == sf::seconds(1));
|
CHECK(offset == sf::seconds(1));
|
||||||
|
@ -2,6 +2,7 @@
|
|||||||
|
|
||||||
#include <type_traits>
|
#include <type_traits>
|
||||||
|
|
||||||
|
static_assert(std::is_default_constructible_v<sf::OutputSoundFile>);
|
||||||
static_assert(!std::is_copy_constructible_v<sf::OutputSoundFile>);
|
static_assert(!std::is_copy_constructible_v<sf::OutputSoundFile>);
|
||||||
static_assert(!std::is_copy_assignable_v<sf::OutputSoundFile>);
|
static_assert(!std::is_copy_assignable_v<sf::OutputSoundFile>);
|
||||||
static_assert(std::is_nothrow_move_constructible_v<sf::OutputSoundFile>);
|
static_assert(std::is_nothrow_move_constructible_v<sf::OutputSoundFile>);
|
||||||
|
@ -26,7 +26,7 @@ TEST_CASE("[Audio] sf::Sound", runAudioDeviceTests())
|
|||||||
STATIC_CHECK(std::has_virtual_destructor_v<sf::Sound>);
|
STATIC_CHECK(std::has_virtual_destructor_v<sf::Sound>);
|
||||||
}
|
}
|
||||||
|
|
||||||
const auto soundBuffer = sf::SoundBuffer::createFromFile("Audio/ding.flac").value();
|
const sf::SoundBuffer soundBuffer("Audio/ding.flac");
|
||||||
|
|
||||||
SECTION("Construction")
|
SECTION("Construction")
|
||||||
{
|
{
|
||||||
@ -52,7 +52,7 @@ TEST_CASE("[Audio] sf::Sound", runAudioDeviceTests())
|
|||||||
|
|
||||||
SECTION("Assignment")
|
SECTION("Assignment")
|
||||||
{
|
{
|
||||||
const sf::SoundBuffer otherSoundBuffer = sf::SoundBuffer::createFromFile("Audio/ding.flac").value();
|
const sf::SoundBuffer otherSoundBuffer("Audio/ding.flac");
|
||||||
sf::Sound soundCopy(otherSoundBuffer);
|
sf::Sound soundCopy(otherSoundBuffer);
|
||||||
soundCopy = sound;
|
soundCopy = sound;
|
||||||
CHECK(&soundCopy.getBuffer() == &soundBuffer);
|
CHECK(&soundCopy.getBuffer() == &soundBuffer);
|
||||||
@ -64,7 +64,7 @@ TEST_CASE("[Audio] sf::Sound", runAudioDeviceTests())
|
|||||||
|
|
||||||
SECTION("Set/get buffer")
|
SECTION("Set/get buffer")
|
||||||
{
|
{
|
||||||
const sf::SoundBuffer otherSoundBuffer = sf::SoundBuffer::createFromFile("Audio/ding.flac").value();
|
const sf::SoundBuffer otherSoundBuffer("Audio/ding.flac");
|
||||||
sf::Sound sound(soundBuffer);
|
sf::Sound sound(soundBuffer);
|
||||||
sound.setBuffer(otherSoundBuffer);
|
sound.setBuffer(otherSoundBuffer);
|
||||||
CHECK(&sound.getBuffer() == &otherSoundBuffer);
|
CHECK(&sound.getBuffer() == &otherSoundBuffer);
|
||||||
|
@ -24,17 +24,69 @@ TEST_CASE("[Audio] sf::SoundBuffer", runAudioDeviceTests())
|
|||||||
|
|
||||||
SECTION("Construction")
|
SECTION("Construction")
|
||||||
{
|
{
|
||||||
const sf::SoundBuffer soundBuffer;
|
SECTION("Default constructor")
|
||||||
CHECK(soundBuffer.getSamples() == nullptr);
|
{
|
||||||
CHECK(soundBuffer.getSampleCount() == 0);
|
const sf::SoundBuffer soundBuffer;
|
||||||
CHECK(soundBuffer.getSampleRate() == 44100);
|
CHECK(soundBuffer.getSamples() == nullptr);
|
||||||
CHECK(soundBuffer.getChannelCount() == 1);
|
CHECK(soundBuffer.getSampleCount() == 0);
|
||||||
CHECK(soundBuffer.getDuration() == sf::Time::Zero);
|
CHECK(soundBuffer.getSampleRate() == 44100);
|
||||||
|
CHECK(soundBuffer.getChannelCount() == 1);
|
||||||
|
CHECK(soundBuffer.getDuration() == sf::Time::Zero);
|
||||||
|
}
|
||||||
|
|
||||||
|
SECTION("File")
|
||||||
|
{
|
||||||
|
SECTION("Invalid filename")
|
||||||
|
{
|
||||||
|
CHECK_THROWS_AS(sf::SoundBuffer("does/not/exist.wav"), std::runtime_error);
|
||||||
|
}
|
||||||
|
|
||||||
|
SECTION("Valid file")
|
||||||
|
{
|
||||||
|
const sf::SoundBuffer soundBuffer("Audio/ding.flac");
|
||||||
|
CHECK(soundBuffer.getSamples() != nullptr);
|
||||||
|
CHECK(soundBuffer.getSampleCount() == 87798);
|
||||||
|
CHECK(soundBuffer.getSampleRate() == 44100);
|
||||||
|
CHECK(soundBuffer.getChannelCount() == 1);
|
||||||
|
CHECK(soundBuffer.getDuration() == sf::microseconds(1990884));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
SECTION("Memory")
|
||||||
|
{
|
||||||
|
SECTION("Invalid memory")
|
||||||
|
{
|
||||||
|
constexpr std::array<std::byte, 5> memory{};
|
||||||
|
CHECK_THROWS_AS(sf::SoundBuffer(memory.data(), memory.size()), std::runtime_error);
|
||||||
|
}
|
||||||
|
|
||||||
|
SECTION("Valid memory")
|
||||||
|
{
|
||||||
|
const auto memory = loadIntoMemory("Audio/ding.flac");
|
||||||
|
const sf::SoundBuffer soundBuffer(memory.data(), memory.size());
|
||||||
|
CHECK(soundBuffer.getSamples() != nullptr);
|
||||||
|
CHECK(soundBuffer.getSampleCount() == 87798);
|
||||||
|
CHECK(soundBuffer.getSampleRate() == 44100);
|
||||||
|
CHECK(soundBuffer.getChannelCount() == 1);
|
||||||
|
CHECK(soundBuffer.getDuration() == sf::microseconds(1990884));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
SECTION("Stream")
|
||||||
|
{
|
||||||
|
sf::FileInputStream stream("Audio/ding.flac");
|
||||||
|
const sf::SoundBuffer soundBuffer(stream);
|
||||||
|
CHECK(soundBuffer.getSamples() != nullptr);
|
||||||
|
CHECK(soundBuffer.getSampleCount() == 87798);
|
||||||
|
CHECK(soundBuffer.getSampleRate() == 44100);
|
||||||
|
CHECK(soundBuffer.getChannelCount() == 1);
|
||||||
|
CHECK(soundBuffer.getDuration() == sf::microseconds(1990884));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
SECTION("Copy semantics")
|
SECTION("Copy semantics")
|
||||||
{
|
{
|
||||||
const auto soundBuffer = sf::SoundBuffer::createFromFile("Audio/ding.flac").value();
|
const sf::SoundBuffer soundBuffer("Audio/ding.flac");
|
||||||
|
|
||||||
SECTION("Construction")
|
SECTION("Construction")
|
||||||
{
|
{
|
||||||
@ -48,8 +100,8 @@ TEST_CASE("[Audio] sf::SoundBuffer", runAudioDeviceTests())
|
|||||||
|
|
||||||
SECTION("Assignment")
|
SECTION("Assignment")
|
||||||
{
|
{
|
||||||
sf::SoundBuffer soundBufferCopy = sf::SoundBuffer::createFromFile("Audio/doodle_pop.ogg").value();
|
sf::SoundBuffer soundBufferCopy("Audio/doodle_pop.ogg");
|
||||||
soundBufferCopy = soundBuffer;
|
soundBufferCopy = soundBuffer;
|
||||||
CHECK(soundBufferCopy.getSamples() != nullptr);
|
CHECK(soundBufferCopy.getSamples() != nullptr);
|
||||||
CHECK(soundBufferCopy.getSampleCount() == 87798);
|
CHECK(soundBufferCopy.getSampleCount() == 87798);
|
||||||
CHECK(soundBufferCopy.getSampleRate() == 44100);
|
CHECK(soundBufferCopy.getSampleRate() == 44100);
|
||||||
@ -123,65 +175,16 @@ TEST_CASE("[Audio] sf::SoundBuffer", runAudioDeviceTests())
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
SECTION("createFromFile()")
|
|
||||||
{
|
|
||||||
SECTION("Invalid filename")
|
|
||||||
{
|
|
||||||
CHECK(!sf::SoundBuffer::createFromFile("does/not/exist.wav"));
|
|
||||||
}
|
|
||||||
|
|
||||||
SECTION("Valid file")
|
|
||||||
{
|
|
||||||
const auto soundBuffer = sf::SoundBuffer::createFromFile("Audio/ding.flac").value();
|
|
||||||
CHECK(soundBuffer.getSamples() != nullptr);
|
|
||||||
CHECK(soundBuffer.getSampleCount() == 87798);
|
|
||||||
CHECK(soundBuffer.getSampleRate() == 44100);
|
|
||||||
CHECK(soundBuffer.getChannelCount() == 1);
|
|
||||||
CHECK(soundBuffer.getDuration() == sf::microseconds(1990884));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
SECTION("createFromMemory()")
|
|
||||||
{
|
|
||||||
SECTION("Invalid memory")
|
|
||||||
{
|
|
||||||
constexpr std::array<std::byte, 5> memory{};
|
|
||||||
CHECK(!sf::SoundBuffer::createFromMemory(memory.data(), memory.size()));
|
|
||||||
}
|
|
||||||
|
|
||||||
SECTION("Valid memory")
|
|
||||||
{
|
|
||||||
const auto memory = loadIntoMemory("Audio/ding.flac");
|
|
||||||
const auto soundBuffer = sf::SoundBuffer::createFromMemory(memory.data(), memory.size()).value();
|
|
||||||
CHECK(soundBuffer.getSamples() != nullptr);
|
|
||||||
CHECK(soundBuffer.getSampleCount() == 87798);
|
|
||||||
CHECK(soundBuffer.getSampleRate() == 44100);
|
|
||||||
CHECK(soundBuffer.getChannelCount() == 1);
|
|
||||||
CHECK(soundBuffer.getDuration() == sf::microseconds(1990884));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
SECTION("createFromStream()")
|
|
||||||
{
|
|
||||||
auto stream = sf::FileInputStream::create("Audio/ding.flac").value();
|
|
||||||
const auto soundBuffer = sf::SoundBuffer::createFromStream(stream).value();
|
|
||||||
CHECK(soundBuffer.getSamples() != nullptr);
|
|
||||||
CHECK(soundBuffer.getSampleCount() == 87798);
|
|
||||||
CHECK(soundBuffer.getSampleRate() == 44100);
|
|
||||||
CHECK(soundBuffer.getChannelCount() == 1);
|
|
||||||
CHECK(soundBuffer.getDuration() == sf::microseconds(1990884));
|
|
||||||
}
|
|
||||||
|
|
||||||
SECTION("saveToFile()")
|
SECTION("saveToFile()")
|
||||||
{
|
{
|
||||||
const auto filename = std::filesystem::temp_directory_path() / "ding.flac";
|
const auto filename = std::filesystem::temp_directory_path() / "ding.flac";
|
||||||
|
|
||||||
{
|
{
|
||||||
const auto soundBuffer = sf::SoundBuffer::createFromFile("Audio/ding.flac").value();
|
const sf::SoundBuffer soundBuffer("Audio/ding.flac");
|
||||||
REQUIRE(soundBuffer.saveToFile(filename));
|
REQUIRE(soundBuffer.saveToFile(filename));
|
||||||
}
|
}
|
||||||
|
|
||||||
const auto soundBuffer = sf::SoundBuffer::createFromFile(filename).value();
|
const sf::SoundBuffer soundBuffer(filename);
|
||||||
CHECK(soundBuffer.getSamples() != nullptr);
|
CHECK(soundBuffer.getSamples() != nullptr);
|
||||||
CHECK(soundBuffer.getSampleCount() == 87798);
|
CHECK(soundBuffer.getSampleCount() == 87798);
|
||||||
CHECK(soundBuffer.getSampleRate() == 44100);
|
CHECK(soundBuffer.getSampleRate() == 44100);
|
||||||
|
@ -11,7 +11,6 @@
|
|||||||
#include <catch2/catch_test_macros.hpp>
|
#include <catch2/catch_test_macros.hpp>
|
||||||
|
|
||||||
#include <filesystem>
|
#include <filesystem>
|
||||||
#include <optional>
|
|
||||||
#include <type_traits>
|
#include <type_traits>
|
||||||
|
|
||||||
#include <cstdint>
|
#include <cstdint>
|
||||||
@ -110,30 +109,29 @@ TEST_CASE("[Audio] sf::SoundFileFactory")
|
|||||||
|
|
||||||
SECTION("createReaderFromStream()")
|
SECTION("createReaderFromStream()")
|
||||||
{
|
{
|
||||||
std::optional<sf::FileInputStream> stream;
|
sf::FileInputStream stream;
|
||||||
|
|
||||||
SECTION("flac")
|
SECTION("flac")
|
||||||
{
|
{
|
||||||
stream = sf::FileInputStream::create("Audio/ding.flac");
|
REQUIRE(stream.open("Audio/ding.flac"));
|
||||||
}
|
}
|
||||||
|
|
||||||
SECTION("mp3")
|
SECTION("mp3")
|
||||||
{
|
{
|
||||||
stream = sf::FileInputStream::create("Audio/ding.mp3");
|
REQUIRE(stream.open("Audio/ding.mp3"));
|
||||||
}
|
}
|
||||||
|
|
||||||
SECTION("ogg")
|
SECTION("ogg")
|
||||||
{
|
{
|
||||||
stream = sf::FileInputStream::create("Audio/doodle_pop.ogg");
|
REQUIRE(stream.open("Audio/doodle_pop.ogg"));
|
||||||
}
|
}
|
||||||
|
|
||||||
SECTION("wav")
|
SECTION("wav")
|
||||||
{
|
{
|
||||||
stream = sf::FileInputStream::create("Audio/killdeer.wav");
|
REQUIRE(stream.open("Audio/killdeer.wav"));
|
||||||
}
|
}
|
||||||
|
|
||||||
REQUIRE(stream);
|
CHECK(sf::SoundFileFactory::createReaderFromStream(stream));
|
||||||
CHECK(sf::SoundFileFactory::createReaderFromStream(*stream));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
SECTION("createWriterFromFilename()")
|
SECTION("createWriterFromFilename()")
|
||||||
|
@ -46,7 +46,7 @@ TEST_CASE("[Graphics] sf::Drawable", runDisplayTests())
|
|||||||
SECTION("draw()")
|
SECTION("draw()")
|
||||||
{
|
{
|
||||||
const DrawableTest drawableTest;
|
const DrawableTest drawableTest;
|
||||||
auto renderTexture = sf::RenderTexture::create({32, 32}).value();
|
sf::RenderTexture renderTexture({32, 32});
|
||||||
CHECK(drawableTest.callCount() == 0);
|
CHECK(drawableTest.callCount() == 0);
|
||||||
renderTexture.draw(drawableTest);
|
renderTexture.draw(drawableTest);
|
||||||
CHECK(drawableTest.callCount() == 1);
|
CHECK(drawableTest.callCount() == 1);
|
||||||
|
@ -23,13 +23,114 @@ TEST_CASE("[Graphics] sf::Font", runDisplayTests())
|
|||||||
|
|
||||||
SECTION("Construction")
|
SECTION("Construction")
|
||||||
{
|
{
|
||||||
const sf::Font font;
|
SECTION("Default constructor")
|
||||||
CHECK(font.getInfo().family.empty());
|
{
|
||||||
CHECK(!font.hasGlyph(0));
|
const sf::Font font;
|
||||||
CHECK(font.getLineSpacing(0) == 0);
|
CHECK(font.getInfo().family.empty());
|
||||||
CHECK(font.getUnderlinePosition(0) == 0);
|
CHECK(!font.hasGlyph(0));
|
||||||
CHECK(font.getUnderlineThickness(0) == 0);
|
CHECK(font.getLineSpacing(0) == 0);
|
||||||
CHECK(font.isSmooth());
|
CHECK(font.getUnderlinePosition(0) == 0);
|
||||||
|
CHECK(font.getUnderlineThickness(0) == 0);
|
||||||
|
CHECK(font.isSmooth());
|
||||||
|
}
|
||||||
|
|
||||||
|
SECTION("File")
|
||||||
|
{
|
||||||
|
SECTION("Invalid filename")
|
||||||
|
{
|
||||||
|
CHECK_THROWS_AS(sf::Font("does/not/exist.ttf"), std::runtime_error);
|
||||||
|
}
|
||||||
|
|
||||||
|
SECTION("Successful load")
|
||||||
|
{
|
||||||
|
const sf::Font font("Graphics/tuffy.ttf");
|
||||||
|
CHECK(font.getInfo().family == "Tuffy");
|
||||||
|
const auto& glyph = font.getGlyph(0x45, 16, false);
|
||||||
|
CHECK(glyph.advance == 9);
|
||||||
|
CHECK(glyph.lsbDelta == 9);
|
||||||
|
CHECK(glyph.rsbDelta == 16);
|
||||||
|
CHECK(glyph.bounds == sf::FloatRect({0, -12}, {8, 12}));
|
||||||
|
CHECK(glyph.textureRect == sf::IntRect({2, 5}, {8, 12}));
|
||||||
|
CHECK(font.hasGlyph(0x41));
|
||||||
|
CHECK(font.hasGlyph(0xC0));
|
||||||
|
CHECK(font.getKerning(0x41, 0x42, 12) == -1);
|
||||||
|
CHECK(font.getKerning(0x43, 0x44, 24, true) == 0);
|
||||||
|
CHECK(font.getLineSpacing(24) == 30);
|
||||||
|
CHECK(font.getUnderlinePosition(36) == Approx(2.20312f));
|
||||||
|
CHECK(font.getUnderlineThickness(48) == Approx(1.17188f));
|
||||||
|
const auto& texture = font.getTexture(10);
|
||||||
|
CHECK(texture.getSize() == sf::Vector2u(128, 128));
|
||||||
|
CHECK(texture.isSmooth());
|
||||||
|
CHECK(!texture.isSrgb());
|
||||||
|
CHECK(!texture.isRepeated());
|
||||||
|
CHECK(texture.getNativeHandle() != 0);
|
||||||
|
CHECK(font.isSmooth());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
SECTION("Memory")
|
||||||
|
{
|
||||||
|
SECTION("Invalid data and size")
|
||||||
|
{
|
||||||
|
CHECK_THROWS_AS(sf::Font(nullptr, 1), std::runtime_error);
|
||||||
|
const std::byte testByte{0xCD};
|
||||||
|
CHECK_THROWS_AS(sf::Font(&testByte, 0), std::runtime_error);
|
||||||
|
}
|
||||||
|
|
||||||
|
SECTION("Successful load")
|
||||||
|
{
|
||||||
|
const auto memory = loadIntoMemory("Graphics/tuffy.ttf");
|
||||||
|
const sf::Font font(memory.data(), memory.size());
|
||||||
|
CHECK(font.getInfo().family == "Tuffy");
|
||||||
|
const auto& glyph = font.getGlyph(0x45, 16, false);
|
||||||
|
CHECK(glyph.advance == 9);
|
||||||
|
CHECK(glyph.lsbDelta == 9);
|
||||||
|
CHECK(glyph.rsbDelta == 16);
|
||||||
|
CHECK(glyph.bounds == sf::FloatRect({0, -12}, {8, 12}));
|
||||||
|
CHECK(glyph.textureRect == sf::IntRect({2, 5}, {8, 12}));
|
||||||
|
CHECK(font.hasGlyph(0x41));
|
||||||
|
CHECK(font.hasGlyph(0xC0));
|
||||||
|
CHECK(font.getKerning(0x41, 0x42, 12) == -1);
|
||||||
|
CHECK(font.getKerning(0x43, 0x44, 24, true) == 0);
|
||||||
|
CHECK(font.getLineSpacing(24) == 30);
|
||||||
|
CHECK(font.getUnderlinePosition(36) == Approx(2.20312f));
|
||||||
|
CHECK(font.getUnderlineThickness(48) == Approx(1.17188f));
|
||||||
|
const auto& texture = font.getTexture(10);
|
||||||
|
CHECK(texture.getSize() == sf::Vector2u(128, 128));
|
||||||
|
CHECK(texture.isSmooth());
|
||||||
|
CHECK(!texture.isSrgb());
|
||||||
|
CHECK(!texture.isRepeated());
|
||||||
|
CHECK(texture.getNativeHandle() != 0);
|
||||||
|
CHECK(font.isSmooth());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
SECTION("Stream")
|
||||||
|
{
|
||||||
|
sf::FileInputStream stream("Graphics/tuffy.ttf");
|
||||||
|
const sf::Font font(stream);
|
||||||
|
CHECK(font.getInfo().family == "Tuffy");
|
||||||
|
const auto& glyph = font.getGlyph(0x45, 16, false);
|
||||||
|
CHECK(glyph.advance == 9);
|
||||||
|
CHECK(glyph.lsbDelta == 9);
|
||||||
|
CHECK(glyph.rsbDelta == 16);
|
||||||
|
CHECK(glyph.bounds == sf::FloatRect({0, -12}, {8, 12}));
|
||||||
|
CHECK(glyph.textureRect == sf::IntRect({2, 5}, {8, 12}));
|
||||||
|
CHECK(font.hasGlyph(0x41));
|
||||||
|
CHECK(font.hasGlyph(0xC0));
|
||||||
|
CHECK(font.getKerning(0x41, 0x42, 12) == -1);
|
||||||
|
CHECK(font.getKerning(0x43, 0x44, 24, true) == 0);
|
||||||
|
CHECK(font.getLineSpacing(24) == 30);
|
||||||
|
CHECK(font.getUnderlinePosition(36) == Approx(2.20312f));
|
||||||
|
CHECK(font.getUnderlineThickness(48) == Approx(1.17188f));
|
||||||
|
const auto& texture = font.getTexture(10);
|
||||||
|
CHECK(texture.getSize() == sf::Vector2u(128, 128));
|
||||||
|
CHECK(texture.isSmooth());
|
||||||
|
CHECK(!texture.isSrgb());
|
||||||
|
CHECK(!texture.isRepeated());
|
||||||
|
CHECK(texture.getNativeHandle() != 0);
|
||||||
|
CHECK(font.isSmooth());
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
SECTION("openFromFile()")
|
SECTION("openFromFile()")
|
||||||
@ -145,107 +246,9 @@ TEST_CASE("[Graphics] sf::Font", runDisplayTests())
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
SECTION("createFromFile()")
|
|
||||||
{
|
|
||||||
SECTION("Invalid filename")
|
|
||||||
{
|
|
||||||
CHECK(!sf::Font::createFromFile("does/not/exist.ttf"));
|
|
||||||
}
|
|
||||||
|
|
||||||
SECTION("Valid file")
|
|
||||||
{
|
|
||||||
const auto font = sf::Font::createFromFile("Graphics/tuffy.ttf").value();
|
|
||||||
CHECK(font.getInfo().family == "Tuffy");
|
|
||||||
const auto& glyph = font.getGlyph(0x45, 16, false);
|
|
||||||
CHECK(glyph.advance == 9);
|
|
||||||
CHECK(glyph.lsbDelta == 9);
|
|
||||||
CHECK(glyph.rsbDelta == 16);
|
|
||||||
CHECK(glyph.bounds == sf::FloatRect({0, -12}, {8, 12}));
|
|
||||||
CHECK(glyph.textureRect == sf::IntRect({2, 5}, {8, 12}));
|
|
||||||
CHECK(font.hasGlyph(0x41));
|
|
||||||
CHECK(font.hasGlyph(0xC0));
|
|
||||||
CHECK(font.getKerning(0x41, 0x42, 12) == -1);
|
|
||||||
CHECK(font.getKerning(0x43, 0x44, 24, true) == 0);
|
|
||||||
CHECK(font.getLineSpacing(24) == 30);
|
|
||||||
CHECK(font.getUnderlinePosition(36) == Approx(2.20312f));
|
|
||||||
CHECK(font.getUnderlineThickness(48) == Approx(1.17188f));
|
|
||||||
const auto& texture = font.getTexture(10);
|
|
||||||
CHECK(texture.getSize() == sf::Vector2u(128, 128));
|
|
||||||
CHECK(texture.isSmooth());
|
|
||||||
CHECK(!texture.isSrgb());
|
|
||||||
CHECK(!texture.isRepeated());
|
|
||||||
CHECK(texture.getNativeHandle() != 0);
|
|
||||||
CHECK(font.isSmooth());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
SECTION("createFromMemory()")
|
|
||||||
{
|
|
||||||
SECTION("Invalid data and size")
|
|
||||||
{
|
|
||||||
CHECK(!sf::Font::createFromMemory(nullptr, 1));
|
|
||||||
const std::byte testByte{0xCD};
|
|
||||||
CHECK(!sf::Font::createFromMemory(&testByte, 0));
|
|
||||||
}
|
|
||||||
|
|
||||||
SECTION("Valid data")
|
|
||||||
{
|
|
||||||
const auto memory = loadIntoMemory("Graphics/tuffy.ttf");
|
|
||||||
const auto font = sf::Font::createFromMemory(memory.data(), memory.size()).value();
|
|
||||||
CHECK(font.getInfo().family == "Tuffy");
|
|
||||||
const auto& glyph = font.getGlyph(0x45, 16, false);
|
|
||||||
CHECK(glyph.advance == 9);
|
|
||||||
CHECK(glyph.lsbDelta == 9);
|
|
||||||
CHECK(glyph.rsbDelta == 16);
|
|
||||||
CHECK(glyph.bounds == sf::FloatRect({0, -12}, {8, 12}));
|
|
||||||
CHECK(glyph.textureRect == sf::IntRect({2, 5}, {8, 12}));
|
|
||||||
CHECK(font.hasGlyph(0x41));
|
|
||||||
CHECK(font.hasGlyph(0xC0));
|
|
||||||
CHECK(font.getKerning(0x41, 0x42, 12) == -1);
|
|
||||||
CHECK(font.getKerning(0x43, 0x44, 24, true) == 0);
|
|
||||||
CHECK(font.getLineSpacing(24) == 30);
|
|
||||||
CHECK(font.getUnderlinePosition(36) == Approx(2.20312f));
|
|
||||||
CHECK(font.getUnderlineThickness(48) == Approx(1.17188f));
|
|
||||||
const auto& texture = font.getTexture(10);
|
|
||||||
CHECK(texture.getSize() == sf::Vector2u(128, 128));
|
|
||||||
CHECK(texture.isSmooth());
|
|
||||||
CHECK(!texture.isSrgb());
|
|
||||||
CHECK(!texture.isRepeated());
|
|
||||||
CHECK(texture.getNativeHandle() != 0);
|
|
||||||
CHECK(font.isSmooth());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
SECTION("createFromStream()")
|
|
||||||
{
|
|
||||||
auto stream = sf::FileInputStream::create("Graphics/tuffy.ttf").value();
|
|
||||||
const auto font = sf::Font::createFromStream(stream).value();
|
|
||||||
CHECK(font.getInfo().family == "Tuffy");
|
|
||||||
const auto& glyph = font.getGlyph(0x45, 16, false);
|
|
||||||
CHECK(glyph.advance == 9);
|
|
||||||
CHECK(glyph.lsbDelta == 9);
|
|
||||||
CHECK(glyph.rsbDelta == 16);
|
|
||||||
CHECK(glyph.bounds == sf::FloatRect({0, -12}, {8, 12}));
|
|
||||||
CHECK(glyph.textureRect == sf::IntRect({2, 5}, {8, 12}));
|
|
||||||
CHECK(font.hasGlyph(0x41));
|
|
||||||
CHECK(font.hasGlyph(0xC0));
|
|
||||||
CHECK(font.getKerning(0x41, 0x42, 12) == -1);
|
|
||||||
CHECK(font.getKerning(0x43, 0x44, 24, true) == 0);
|
|
||||||
CHECK(font.getLineSpacing(24) == 30);
|
|
||||||
CHECK(font.getUnderlinePosition(36) == Approx(2.20312f));
|
|
||||||
CHECK(font.getUnderlineThickness(48) == Approx(1.17188f));
|
|
||||||
const auto& texture = font.getTexture(10);
|
|
||||||
CHECK(texture.getSize() == sf::Vector2u(128, 128));
|
|
||||||
CHECK(texture.isSmooth());
|
|
||||||
CHECK(!texture.isSrgb());
|
|
||||||
CHECK(!texture.isRepeated());
|
|
||||||
CHECK(texture.getNativeHandle() != 0);
|
|
||||||
CHECK(font.isSmooth());
|
|
||||||
}
|
|
||||||
|
|
||||||
SECTION("Set/get smooth")
|
SECTION("Set/get smooth")
|
||||||
{
|
{
|
||||||
auto font = sf::Font::createFromFile("Graphics/tuffy.ttf").value();
|
sf::Font font("Graphics/tuffy.ttf");
|
||||||
font.setSmooth(false);
|
font.setSmooth(false);
|
||||||
CHECK(!font.isSmooth());
|
CHECK(!font.isSmooth());
|
||||||
}
|
}
|
||||||
|
@ -19,15 +19,123 @@ TEST_CASE("[Graphics] sf::Image")
|
|||||||
STATIC_CHECK(std::is_nothrow_move_assignable_v<sf::Image>);
|
STATIC_CHECK(std::is_nothrow_move_assignable_v<sf::Image>);
|
||||||
}
|
}
|
||||||
|
|
||||||
SECTION("Default constructor")
|
|
||||||
{
|
|
||||||
const sf::Image image;
|
|
||||||
CHECK(image.getSize() == sf::Vector2u());
|
|
||||||
CHECK(image.getPixelsPtr() == nullptr);
|
|
||||||
}
|
|
||||||
|
|
||||||
SECTION("Construction")
|
SECTION("Construction")
|
||||||
{
|
{
|
||||||
|
SECTION("Default constructor")
|
||||||
|
{
|
||||||
|
const sf::Image image;
|
||||||
|
CHECK(image.getSize() == sf::Vector2u());
|
||||||
|
CHECK(image.getPixelsPtr() == nullptr);
|
||||||
|
}
|
||||||
|
|
||||||
|
SECTION("File constructor")
|
||||||
|
{
|
||||||
|
SECTION("Invalid file")
|
||||||
|
{
|
||||||
|
CHECK_THROWS_AS(sf::Image("."), std::runtime_error);
|
||||||
|
CHECK_THROWS_AS(sf::Image("this/does/not/exist.jpg"), std::runtime_error);
|
||||||
|
}
|
||||||
|
|
||||||
|
SECTION("Successful load")
|
||||||
|
{
|
||||||
|
SECTION("bmp")
|
||||||
|
{
|
||||||
|
const sf::Image image("Graphics/sfml-logo-big.bmp");
|
||||||
|
CHECK(image.getPixel({0, 0}) == sf::Color::White);
|
||||||
|
CHECK(image.getPixel({200, 150}) == sf::Color(144, 208, 62));
|
||||||
|
CHECK(image.getSize() == sf::Vector2u(1001, 304));
|
||||||
|
CHECK(image.getPixelsPtr() != nullptr);
|
||||||
|
}
|
||||||
|
|
||||||
|
SECTION("png")
|
||||||
|
{
|
||||||
|
const sf::Image image("Graphics/sfml-logo-big.png");
|
||||||
|
CHECK(image.getPixel({0, 0}) == sf::Color(255, 255, 255, 0));
|
||||||
|
CHECK(image.getPixel({200, 150}) == sf::Color(144, 208, 62));
|
||||||
|
CHECK(image.getSize() == sf::Vector2u(1001, 304));
|
||||||
|
CHECK(image.getPixelsPtr() != nullptr);
|
||||||
|
}
|
||||||
|
|
||||||
|
SECTION("jpg")
|
||||||
|
{
|
||||||
|
const sf::Image image("Graphics/sfml-logo-big.jpg");
|
||||||
|
CHECK(image.getPixel({0, 0}) == sf::Color::White);
|
||||||
|
CHECK(image.getPixel({200, 150}) == sf::Color(144, 208, 62));
|
||||||
|
CHECK(image.getSize() == sf::Vector2u(1001, 304));
|
||||||
|
CHECK(image.getPixelsPtr() != nullptr);
|
||||||
|
}
|
||||||
|
|
||||||
|
SECTION("gif")
|
||||||
|
{
|
||||||
|
const sf::Image image("Graphics/sfml-logo-big.gif");
|
||||||
|
CHECK(image.getPixel({0, 0}) == sf::Color::White);
|
||||||
|
CHECK(image.getPixel({200, 150}) == sf::Color(146, 210, 62));
|
||||||
|
CHECK(image.getSize() == sf::Vector2u(1001, 304));
|
||||||
|
CHECK(image.getPixelsPtr() != nullptr);
|
||||||
|
}
|
||||||
|
|
||||||
|
SECTION("psd")
|
||||||
|
{
|
||||||
|
const sf::Image image("Graphics/sfml-logo-big.psd");
|
||||||
|
CHECK(image.getPixel({0, 0}) == sf::Color::White);
|
||||||
|
CHECK(image.getPixel({200, 150}) == sf::Color(144, 208, 62));
|
||||||
|
CHECK(image.getSize() == sf::Vector2u(1001, 304));
|
||||||
|
CHECK(image.getPixelsPtr() != nullptr);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
SECTION("Memory constructor")
|
||||||
|
{
|
||||||
|
SECTION("Invalid pointer")
|
||||||
|
{
|
||||||
|
CHECK_THROWS_AS(sf::Image(nullptr, 1), std::runtime_error);
|
||||||
|
}
|
||||||
|
|
||||||
|
SECTION("Invalid size")
|
||||||
|
{
|
||||||
|
const std::byte testByte{0xAB};
|
||||||
|
CHECK_THROWS_AS(sf::Image(&testByte, 0), std::runtime_error);
|
||||||
|
}
|
||||||
|
|
||||||
|
SECTION("Failed load")
|
||||||
|
{
|
||||||
|
std::vector<std::uint8_t> memory;
|
||||||
|
|
||||||
|
SECTION("Empty")
|
||||||
|
{
|
||||||
|
memory.clear();
|
||||||
|
}
|
||||||
|
|
||||||
|
SECTION("Junk data")
|
||||||
|
{
|
||||||
|
memory = {1, 2, 3, 4};
|
||||||
|
}
|
||||||
|
|
||||||
|
CHECK_THROWS_AS(sf::Image(memory.data(), memory.size()), std::runtime_error);
|
||||||
|
}
|
||||||
|
|
||||||
|
SECTION("Successful load")
|
||||||
|
{
|
||||||
|
const auto memory = sf::Image({24, 24}, sf::Color::Green).saveToMemory("png").value();
|
||||||
|
const sf::Image image(memory.data(), memory.size());
|
||||||
|
CHECK(image.getSize() == sf::Vector2u(24, 24));
|
||||||
|
CHECK(image.getPixelsPtr() != nullptr);
|
||||||
|
CHECK(image.getPixel({0, 0}) == sf::Color::Green);
|
||||||
|
CHECK(image.getPixel({23, 23}) == sf::Color::Green);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
SECTION("Stream constructor")
|
||||||
|
{
|
||||||
|
sf::FileInputStream stream("Graphics/sfml-logo-big.png");
|
||||||
|
const sf::Image image(stream);
|
||||||
|
CHECK(image.getSize() == sf::Vector2u(1001, 304));
|
||||||
|
CHECK(image.getPixelsPtr() != nullptr);
|
||||||
|
CHECK(image.getPixel({0, 0}) == sf::Color(255, 255, 255, 0));
|
||||||
|
CHECK(image.getPixel({200, 150}) == sf::Color(144, 208, 62));
|
||||||
|
}
|
||||||
|
|
||||||
SECTION("Vector2 constructor")
|
SECTION("Vector2 constructor")
|
||||||
{
|
{
|
||||||
const sf::Image image(sf::Vector2u(10, 10));
|
const sf::Image image(sf::Vector2u(10, 10));
|
||||||
@ -272,114 +380,6 @@ TEST_CASE("[Graphics] sf::Image")
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
SECTION("createFromFile()")
|
|
||||||
{
|
|
||||||
SECTION("Invalid file")
|
|
||||||
{
|
|
||||||
CHECK(!sf::Image::createFromFile("."));
|
|
||||||
CHECK(!sf::Image::createFromFile("this/does/not/exist.jpg"));
|
|
||||||
}
|
|
||||||
|
|
||||||
SECTION("Successful load")
|
|
||||||
{
|
|
||||||
std::optional<sf::Image> image;
|
|
||||||
|
|
||||||
SECTION("bmp")
|
|
||||||
{
|
|
||||||
image = sf::Image::createFromFile("Graphics/sfml-logo-big.bmp").value();
|
|
||||||
REQUIRE(image.has_value());
|
|
||||||
CHECK(image->getPixel({0, 0}) == sf::Color::White);
|
|
||||||
CHECK(image->getPixel({200, 150}) == sf::Color(144, 208, 62));
|
|
||||||
}
|
|
||||||
|
|
||||||
SECTION("png")
|
|
||||||
{
|
|
||||||
image = sf::Image::createFromFile("Graphics/sfml-logo-big.png").value();
|
|
||||||
REQUIRE(image.has_value());
|
|
||||||
CHECK(image->getPixel({0, 0}) == sf::Color(255, 255, 255, 0));
|
|
||||||
CHECK(image->getPixel({200, 150}) == sf::Color(144, 208, 62));
|
|
||||||
}
|
|
||||||
|
|
||||||
SECTION("jpg")
|
|
||||||
{
|
|
||||||
image = sf::Image::createFromFile("Graphics/sfml-logo-big.jpg").value();
|
|
||||||
REQUIRE(image.has_value());
|
|
||||||
CHECK(image->getPixel({0, 0}) == sf::Color::White);
|
|
||||||
CHECK(image->getPixel({200, 150}) == sf::Color(144, 208, 62));
|
|
||||||
}
|
|
||||||
|
|
||||||
SECTION("gif")
|
|
||||||
{
|
|
||||||
image = sf::Image::createFromFile("Graphics/sfml-logo-big.gif").value();
|
|
||||||
REQUIRE(image.has_value());
|
|
||||||
CHECK(image->getPixel({0, 0}) == sf::Color::White);
|
|
||||||
CHECK(image->getPixel({200, 150}) == sf::Color(146, 210, 62));
|
|
||||||
}
|
|
||||||
|
|
||||||
SECTION("psd")
|
|
||||||
{
|
|
||||||
image = sf::Image::createFromFile("Graphics/sfml-logo-big.psd").value();
|
|
||||||
REQUIRE(image.has_value());
|
|
||||||
CHECK(image->getPixel({0, 0}) == sf::Color::White);
|
|
||||||
CHECK(image->getPixel({200, 150}) == sf::Color(144, 208, 62));
|
|
||||||
}
|
|
||||||
|
|
||||||
CHECK(image->getSize() == sf::Vector2u(1001, 304));
|
|
||||||
CHECK(image->getPixelsPtr() != nullptr);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
SECTION("createFromMemory()")
|
|
||||||
{
|
|
||||||
SECTION("Invalid pointer")
|
|
||||||
{
|
|
||||||
CHECK(!sf::Image::createFromMemory(nullptr, 1));
|
|
||||||
}
|
|
||||||
|
|
||||||
SECTION("Invalid size")
|
|
||||||
{
|
|
||||||
const std::byte testByte{0xAB};
|
|
||||||
CHECK(!sf::Image::createFromMemory(&testByte, 0));
|
|
||||||
}
|
|
||||||
|
|
||||||
SECTION("Failed load")
|
|
||||||
{
|
|
||||||
std::vector<std::uint8_t> memory;
|
|
||||||
|
|
||||||
SECTION("Empty")
|
|
||||||
{
|
|
||||||
memory.clear();
|
|
||||||
}
|
|
||||||
|
|
||||||
SECTION("Junk data")
|
|
||||||
{
|
|
||||||
memory = {1, 2, 3, 4};
|
|
||||||
}
|
|
||||||
|
|
||||||
CHECK(!sf::Image::createFromMemory(memory.data(), memory.size()));
|
|
||||||
}
|
|
||||||
|
|
||||||
SECTION("Successful load")
|
|
||||||
{
|
|
||||||
const auto memory = sf::Image({24, 24}, sf::Color::Green).saveToMemory("png").value();
|
|
||||||
const auto image = sf::Image::createFromMemory(memory.data(), memory.size()).value();
|
|
||||||
CHECK(image.getSize() == sf::Vector2u(24, 24));
|
|
||||||
CHECK(image.getPixelsPtr() != nullptr);
|
|
||||||
CHECK(image.getPixel({0, 0}) == sf::Color::Green);
|
|
||||||
CHECK(image.getPixel({23, 23}) == sf::Color::Green);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
SECTION("createFromStream()")
|
|
||||||
{
|
|
||||||
auto stream = sf::FileInputStream::create("Graphics/sfml-logo-big.png").value();
|
|
||||||
const auto image = sf::Image::createFromStream(stream).value();
|
|
||||||
CHECK(image.getSize() == sf::Vector2u(1001, 304));
|
|
||||||
CHECK(image.getPixelsPtr() != nullptr);
|
|
||||||
CHECK(image.getPixel({0, 0}) == sf::Color(255, 255, 255, 0));
|
|
||||||
CHECK(image.getPixel({200, 150}) == sf::Color(144, 208, 62));
|
|
||||||
}
|
|
||||||
|
|
||||||
SECTION("saveToFile()")
|
SECTION("saveToFile()")
|
||||||
{
|
{
|
||||||
SECTION("Invalid size")
|
SECTION("Invalid size")
|
||||||
@ -426,7 +426,7 @@ TEST_CASE("[Graphics] sf::Image")
|
|||||||
|
|
||||||
// Cannot test JPEG encoding due to it triggering UB in stbiw__jpg_writeBits
|
// Cannot test JPEG encoding due to it triggering UB in stbiw__jpg_writeBits
|
||||||
|
|
||||||
const auto loadedImage = sf::Image::createFromFile(filename).value();
|
const sf::Image loadedImage(filename);
|
||||||
CHECK(loadedImage.getSize() == sf::Vector2u(256, 256));
|
CHECK(loadedImage.getSize() == sf::Vector2u(256, 256));
|
||||||
CHECK(loadedImage.getPixelsPtr() != nullptr);
|
CHECK(loadedImage.getPixelsPtr() != nullptr);
|
||||||
|
|
||||||
|
@ -12,9 +12,7 @@ TEST_CASE("[Graphics] Render Tests", runDisplayTests())
|
|||||||
{
|
{
|
||||||
SECTION("Stencil Tests")
|
SECTION("Stencil Tests")
|
||||||
{
|
{
|
||||||
auto renderTexture = sf::RenderTexture::create({100, 100}, sf::ContextSettings{0 /* depthBits */, 8 /* stencilBits */})
|
sf::RenderTexture renderTexture({100, 100}, sf::ContextSettings{0 /* depthBits */, 8 /* stencilBits */});
|
||||||
.value();
|
|
||||||
|
|
||||||
renderTexture.clear(sf::Color::Red, 127);
|
renderTexture.clear(sf::Color::Red, 127);
|
||||||
|
|
||||||
sf::RectangleShape shape1({100, 100});
|
sf::RectangleShape shape1({100, 100});
|
||||||
|
@ -17,20 +17,45 @@ TEST_CASE("[Graphics] sf::RenderTexture", runDisplayTests())
|
|||||||
|
|
||||||
SECTION("Construction")
|
SECTION("Construction")
|
||||||
{
|
{
|
||||||
const sf::RenderTexture renderTexture;
|
SECTION("Default constructor")
|
||||||
CHECK(!renderTexture.isSmooth());
|
{
|
||||||
CHECK(!renderTexture.isRepeated());
|
const sf::RenderTexture renderTexture;
|
||||||
CHECK(renderTexture.getSize() == sf::Vector2u(0, 0));
|
CHECK(!renderTexture.isSmooth());
|
||||||
|
CHECK(!renderTexture.isRepeated());
|
||||||
|
CHECK(renderTexture.getSize() == sf::Vector2u(0, 0));
|
||||||
|
}
|
||||||
|
|
||||||
|
SECTION("2 parameter constructor")
|
||||||
|
{
|
||||||
|
CHECK_THROWS_AS(sf::RenderTexture({1'000'000, 1'000'000}), std::runtime_error);
|
||||||
|
|
||||||
|
CHECK_NOTHROW(sf::RenderTexture({100, 100}, sf::ContextSettings{8 /* depthBits */, 0 /* stencilBits */}));
|
||||||
|
CHECK_NOTHROW(sf::RenderTexture({100, 100}, sf::ContextSettings{0 /* depthBits */, 8 /* stencilBits */}));
|
||||||
|
|
||||||
|
const sf::RenderTexture renderTexture({360, 480});
|
||||||
|
CHECK(renderTexture.getSize() == sf::Vector2u(360, 480));
|
||||||
|
CHECK(!renderTexture.isSmooth());
|
||||||
|
CHECK(!renderTexture.isRepeated());
|
||||||
|
CHECK(!renderTexture.isSrgb());
|
||||||
|
|
||||||
|
const auto& texture = renderTexture.getTexture();
|
||||||
|
CHECK(texture.getSize() == sf::Vector2u(360, 480));
|
||||||
|
CHECK(!texture.isSmooth());
|
||||||
|
CHECK(!texture.isSrgb());
|
||||||
|
CHECK(!texture.isRepeated());
|
||||||
|
CHECK(texture.getNativeHandle() != 0);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
SECTION("create()")
|
SECTION("resize()")
|
||||||
{
|
{
|
||||||
CHECK(!sf::RenderTexture::create({1'000'000, 1'000'000}));
|
sf::RenderTexture renderTexture;
|
||||||
|
CHECK(!renderTexture.resize({1'000'000, 1'000'000}));
|
||||||
|
|
||||||
CHECK(sf::RenderTexture::create({100, 100}, sf::ContextSettings{8 /* depthBits */, 0 /* stencilBits */}));
|
CHECK(renderTexture.resize({100, 100}, sf::ContextSettings{8 /* depthBits */, 0 /* stencilBits */}));
|
||||||
CHECK(sf::RenderTexture::create({100, 100}, sf::ContextSettings{0 /* depthBits */, 8 /* stencilBits */}));
|
CHECK(renderTexture.resize({100, 100}, sf::ContextSettings{0 /* depthBits */, 8 /* stencilBits */}));
|
||||||
|
|
||||||
const auto renderTexture = sf::RenderTexture::create({360, 480}).value();
|
REQUIRE(renderTexture.resize({360, 480}));
|
||||||
CHECK(renderTexture.getSize() == sf::Vector2u(360, 480));
|
CHECK(renderTexture.getSize() == sf::Vector2u(360, 480));
|
||||||
CHECK(!renderTexture.isSmooth());
|
CHECK(!renderTexture.isSmooth());
|
||||||
CHECK(!renderTexture.isRepeated());
|
CHECK(!renderTexture.isRepeated());
|
||||||
@ -66,27 +91,27 @@ TEST_CASE("[Graphics] sf::RenderTexture", runDisplayTests())
|
|||||||
|
|
||||||
SECTION("Set/get smooth")
|
SECTION("Set/get smooth")
|
||||||
{
|
{
|
||||||
auto renderTexture = sf::RenderTexture::create({64, 64}).value();
|
sf::RenderTexture renderTexture({64, 64});
|
||||||
renderTexture.setSmooth(true);
|
renderTexture.setSmooth(true);
|
||||||
CHECK(renderTexture.isSmooth());
|
CHECK(renderTexture.isSmooth());
|
||||||
}
|
}
|
||||||
|
|
||||||
SECTION("Set/get repeated")
|
SECTION("Set/get repeated")
|
||||||
{
|
{
|
||||||
auto renderTexture = sf::RenderTexture::create({64, 64}).value();
|
sf::RenderTexture renderTexture({64, 64});
|
||||||
renderTexture.setRepeated(true);
|
renderTexture.setRepeated(true);
|
||||||
CHECK(renderTexture.isRepeated());
|
CHECK(renderTexture.isRepeated());
|
||||||
}
|
}
|
||||||
|
|
||||||
SECTION("generateMipmap()")
|
SECTION("generateMipmap()")
|
||||||
{
|
{
|
||||||
auto renderTexture = sf::RenderTexture::create({64, 64}).value();
|
sf::RenderTexture renderTexture({64, 64});
|
||||||
CHECK(renderTexture.generateMipmap());
|
CHECK(renderTexture.generateMipmap());
|
||||||
}
|
}
|
||||||
|
|
||||||
SECTION("setActive()")
|
SECTION("setActive()")
|
||||||
{
|
{
|
||||||
auto renderTexture = sf::RenderTexture::create({64, 64}).value();
|
sf::RenderTexture renderTexture({64, 64});
|
||||||
CHECK(renderTexture.setActive());
|
CHECK(renderTexture.setActive());
|
||||||
CHECK(renderTexture.setActive(false));
|
CHECK(renderTexture.setActive(false));
|
||||||
CHECK(renderTexture.setActive(true));
|
CHECK(renderTexture.setActive(true));
|
||||||
@ -94,7 +119,7 @@ TEST_CASE("[Graphics] sf::RenderTexture", runDisplayTests())
|
|||||||
|
|
||||||
SECTION("getTexture()")
|
SECTION("getTexture()")
|
||||||
{
|
{
|
||||||
const auto renderTexture = sf::RenderTexture::create({64, 64}).value();
|
const sf::RenderTexture renderTexture({64, 64});
|
||||||
CHECK(renderTexture.getTexture().getSize() == sf::Vector2u(64, 64));
|
CHECK(renderTexture.getTexture().getSize() == sf::Vector2u(64, 64));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -75,7 +75,7 @@ TEST_CASE("[Graphics] sf::RenderWindow", runDisplayTests())
|
|||||||
sf::ContextSettings{});
|
sf::ContextSettings{});
|
||||||
REQUIRE(window.getSize() == sf::Vector2u(256, 256));
|
REQUIRE(window.getSize() == sf::Vector2u(256, 256));
|
||||||
|
|
||||||
auto texture = sf::Texture::create(window.getSize()).value();
|
sf::Texture texture(window.getSize());
|
||||||
|
|
||||||
window.clear(sf::Color::Red);
|
window.clear(sf::Color::Red);
|
||||||
texture.update(window);
|
texture.update(window);
|
||||||
|
@ -145,6 +145,18 @@ TEST_CASE("[Graphics] sf::Shader (Dummy Implementation)", skipShaderDummyTests()
|
|||||||
CHECK_FALSE(sf::Shader::isGeometryAvailable());
|
CHECK_FALSE(sf::Shader::isGeometryAvailable());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
SECTION("Construct from memory")
|
||||||
|
{
|
||||||
|
CHECK_THROWS_AS(sf::Shader(std::string_view(vertexSource), sf::Shader::Type::Vertex), std::runtime_error);
|
||||||
|
CHECK_THROWS_AS(sf::Shader(std::string_view(geometrySource), sf::Shader::Type::Geometry), std::runtime_error);
|
||||||
|
CHECK_THROWS_AS(sf::Shader(std::string_view(fragmentSource), sf::Shader::Type::Fragment), std::runtime_error);
|
||||||
|
CHECK_THROWS_AS(sf::Shader(std::string_view(vertexSource), std::string_view(fragmentSource)), std::runtime_error);
|
||||||
|
CHECK_THROWS_AS(sf::Shader(std::string_view(vertexSource),
|
||||||
|
std::string_view(geometrySource),
|
||||||
|
std::string_view(fragmentSource)),
|
||||||
|
std::runtime_error);
|
||||||
|
}
|
||||||
|
|
||||||
SECTION("loadFromMemory()")
|
SECTION("loadFromMemory()")
|
||||||
{
|
{
|
||||||
sf::Shader shader;
|
sf::Shader shader;
|
||||||
@ -154,15 +166,6 @@ TEST_CASE("[Graphics] sf::Shader (Dummy Implementation)", skipShaderDummyTests()
|
|||||||
CHECK_FALSE(shader.loadFromMemory(vertexSource, fragmentSource));
|
CHECK_FALSE(shader.loadFromMemory(vertexSource, fragmentSource));
|
||||||
CHECK_FALSE(shader.loadFromMemory(vertexSource, geometrySource, fragmentSource));
|
CHECK_FALSE(shader.loadFromMemory(vertexSource, geometrySource, fragmentSource));
|
||||||
}
|
}
|
||||||
|
|
||||||
SECTION("createFromMemory()")
|
|
||||||
{
|
|
||||||
CHECK_FALSE(sf::Shader::createFromMemory(vertexSource, sf::Shader::Type::Vertex).has_value());
|
|
||||||
CHECK_FALSE(sf::Shader::createFromMemory(geometrySource, sf::Shader::Type::Geometry).has_value());
|
|
||||||
CHECK_FALSE(sf::Shader::createFromMemory(fragmentSource, sf::Shader::Type::Fragment).has_value());
|
|
||||||
CHECK_FALSE(sf::Shader::createFromMemory(vertexSource, fragmentSource).has_value());
|
|
||||||
CHECK_FALSE(sf::Shader::createFromMemory(vertexSource, geometrySource, fragmentSource).has_value());
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST_CASE("[Graphics] sf::Shader", skipShaderFullTests())
|
TEST_CASE("[Graphics] sf::Shader", skipShaderFullTests())
|
||||||
@ -177,8 +180,181 @@ TEST_CASE("[Graphics] sf::Shader", skipShaderFullTests())
|
|||||||
|
|
||||||
SECTION("Construction")
|
SECTION("Construction")
|
||||||
{
|
{
|
||||||
const sf::Shader shader;
|
SECTION("Default constructor")
|
||||||
CHECK(shader.getNativeHandle() == 0);
|
{
|
||||||
|
const sf::Shader shader;
|
||||||
|
CHECK(shader.getNativeHandle() == 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
SECTION("File")
|
||||||
|
{
|
||||||
|
SECTION("One shader")
|
||||||
|
{
|
||||||
|
CHECK_THROWS_AS(sf::Shader(std::filesystem::path("does-not-exist.vert"), sf::Shader::Type::Vertex),
|
||||||
|
std::runtime_error);
|
||||||
|
|
||||||
|
if (sf::Shader::isAvailable())
|
||||||
|
{
|
||||||
|
CHECK(sf::Shader(std::filesystem::path("Graphics/shader.vert"), sf::Shader::Type::Vertex).getNativeHandle() !=
|
||||||
|
0);
|
||||||
|
CHECK(sf::Shader(std::filesystem::path("Graphics/shader.frag"), sf::Shader::Type::Fragment)
|
||||||
|
.getNativeHandle() != 0);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
CHECK_THROWS_AS(sf::Shader(std::filesystem::path("Graphics/shader.vert"), sf::Shader::Type::Vertex),
|
||||||
|
std::runtime_error);
|
||||||
|
CHECK_THROWS_AS(sf::Shader(std::filesystem::path("Graphics/shader.frag"), sf::Shader::Type::Fragment),
|
||||||
|
std::runtime_error);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
SECTION("Two shaders")
|
||||||
|
{
|
||||||
|
CHECK_THROWS_AS(sf::Shader(std::filesystem::path("does-not-exist.vert"),
|
||||||
|
std::filesystem::path("Graphics/shader.frag")),
|
||||||
|
std::runtime_error);
|
||||||
|
CHECK_THROWS_AS(sf::Shader(std::filesystem::path("Graphics/shader.vert"),
|
||||||
|
std::filesystem::path("does-not-exist.frag")),
|
||||||
|
std::runtime_error);
|
||||||
|
|
||||||
|
if (sf::Shader::isAvailable())
|
||||||
|
{
|
||||||
|
CHECK(sf::Shader(std::filesystem::path("Graphics/shader.vert"),
|
||||||
|
std::filesystem::path("Graphics/shader.frag"))
|
||||||
|
.getNativeHandle() != 0);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
CHECK_THROWS_AS(sf::Shader(std::filesystem::path("Graphics/shader.vert"),
|
||||||
|
std::filesystem::path("Graphics/shader.frag")),
|
||||||
|
std::runtime_error);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
SECTION("Three shaders")
|
||||||
|
{
|
||||||
|
CHECK_THROWS_AS(sf::Shader(std::filesystem::path("does-not-exist.vert"),
|
||||||
|
std::filesystem::path("Graphics/shader.geom"),
|
||||||
|
std::filesystem::path("Graphics/shader.frag")),
|
||||||
|
std::runtime_error);
|
||||||
|
CHECK_THROWS_AS(sf::Shader(std::filesystem::path("Graphics/shader.vert"),
|
||||||
|
std::filesystem::path("does-not-exist.geom"),
|
||||||
|
std::filesystem::path("Graphics/shader.frag")),
|
||||||
|
std::runtime_error);
|
||||||
|
CHECK_THROWS_AS(sf::Shader(std::filesystem::path("Graphics/shader.vert"),
|
||||||
|
std::filesystem::path("Graphics/shader.geom"),
|
||||||
|
std::filesystem::path("does-not-exist.frag")),
|
||||||
|
std::runtime_error);
|
||||||
|
|
||||||
|
if (sf::Shader::isGeometryAvailable())
|
||||||
|
{
|
||||||
|
CHECK(sf::Shader(std::filesystem::path("Graphics/shader.vert"),
|
||||||
|
std::filesystem::path("Graphics/shader.geom"),
|
||||||
|
std::filesystem::path("Graphics/shader.frag"))
|
||||||
|
.getNativeHandle() != 0);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
CHECK_THROWS_AS(sf::Shader(std::filesystem::path("Graphics/shader.vert"),
|
||||||
|
std::filesystem::path("Graphics/shader.geom"),
|
||||||
|
std::filesystem::path("Graphics/shader.frag")),
|
||||||
|
std::runtime_error);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
SECTION("Memory")
|
||||||
|
{
|
||||||
|
if (sf::Shader::isAvailable())
|
||||||
|
{
|
||||||
|
CHECK(sf::Shader(std::string_view(vertexSource), sf::Shader::Type::Vertex).getNativeHandle() != 0);
|
||||||
|
CHECK_THROWS_AS(sf::Shader(std::string_view(geometrySource), sf::Shader::Type::Geometry),
|
||||||
|
std::runtime_error);
|
||||||
|
CHECK(sf::Shader(std::string_view(fragmentSource), sf::Shader::Type::Fragment).getNativeHandle() != 0);
|
||||||
|
CHECK(sf::Shader(std::string_view(vertexSource), std::string_view(fragmentSource)).getNativeHandle() != 0);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
CHECK_THROWS_AS(sf::Shader(std::string_view(vertexSource), sf::Shader::Type::Vertex), std::runtime_error);
|
||||||
|
CHECK_THROWS_AS(sf::Shader(std::string_view(geometrySource), sf::Shader::Type::Geometry),
|
||||||
|
std::runtime_error);
|
||||||
|
CHECK_THROWS_AS(sf::Shader(std::string_view(fragmentSource), sf::Shader::Type::Fragment),
|
||||||
|
std::runtime_error);
|
||||||
|
CHECK_THROWS_AS(sf::Shader(std::string_view(vertexSource), std::string_view(fragmentSource)),
|
||||||
|
std::runtime_error);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (sf::Shader::isGeometryAvailable())
|
||||||
|
{
|
||||||
|
CHECK(sf::Shader(std::string_view(vertexSource), std::string_view(geometrySource), std::string_view(fragmentSource))
|
||||||
|
.getNativeHandle() != 0);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
CHECK_THROWS_AS(sf::Shader(std::string_view(vertexSource),
|
||||||
|
std::string_view(geometrySource),
|
||||||
|
std::string_view(fragmentSource)),
|
||||||
|
std::runtime_error);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
SECTION("Stream")
|
||||||
|
{
|
||||||
|
sf::FileInputStream vertexShaderStream("Graphics/shader.vert");
|
||||||
|
sf::FileInputStream fragmentShaderStream("Graphics/shader.frag");
|
||||||
|
sf::FileInputStream geometryShaderStream("Graphics/shader.geom");
|
||||||
|
|
||||||
|
sf::FileInputStream emptyStream("Graphics/invalid_shader.vert");
|
||||||
|
|
||||||
|
SECTION("One shader")
|
||||||
|
{
|
||||||
|
CHECK_THROWS_AS(sf::Shader(emptyStream, sf::Shader::Type::Vertex), std::runtime_error);
|
||||||
|
|
||||||
|
if (sf::Shader::isAvailable())
|
||||||
|
{
|
||||||
|
CHECK(sf::Shader(vertexShaderStream, sf::Shader::Type::Vertex).getNativeHandle() != 0);
|
||||||
|
CHECK(sf::Shader(fragmentShaderStream, sf::Shader::Type::Fragment).getNativeHandle() != 0);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
CHECK_THROWS_AS(sf::Shader(vertexShaderStream, sf::Shader::Type::Vertex), std::runtime_error);
|
||||||
|
CHECK_THROWS_AS(sf::Shader(fragmentShaderStream, sf::Shader::Type::Fragment), std::runtime_error);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
SECTION("Two shaders")
|
||||||
|
{
|
||||||
|
CHECK_THROWS_AS(sf::Shader(emptyStream, fragmentShaderStream), std::runtime_error);
|
||||||
|
CHECK_THROWS_AS(sf::Shader(vertexShaderStream, emptyStream), std::runtime_error);
|
||||||
|
|
||||||
|
if (sf::Shader::isAvailable())
|
||||||
|
{
|
||||||
|
CHECK(sf::Shader(vertexShaderStream, fragmentShaderStream).getNativeHandle() != 0);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
CHECK_THROWS_AS(sf::Shader(vertexShaderStream, fragmentShaderStream), std::runtime_error);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
SECTION("Three shaders")
|
||||||
|
{
|
||||||
|
CHECK_THROWS_AS(sf::Shader(emptyStream, geometryShaderStream, fragmentShaderStream), std::runtime_error);
|
||||||
|
CHECK_THROWS_AS(sf::Shader(vertexShaderStream, emptyStream, fragmentShaderStream), std::runtime_error);
|
||||||
|
CHECK_THROWS_AS(sf::Shader(vertexShaderStream, geometryShaderStream, emptyStream), std::runtime_error);
|
||||||
|
|
||||||
|
if (sf::Shader::isGeometryAvailable())
|
||||||
|
{
|
||||||
|
CHECK(sf::Shader(vertexShaderStream, geometryShaderStream, fragmentShaderStream).getNativeHandle() != 0);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
CHECK_THROWS_AS(sf::Shader(vertexShaderStream, geometryShaderStream, fragmentShaderStream),
|
||||||
|
std::runtime_error);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
SECTION("Move semantics")
|
SECTION("Move semantics")
|
||||||
@ -203,16 +379,16 @@ TEST_CASE("[Graphics] sf::Shader", skipShaderFullTests())
|
|||||||
{
|
{
|
||||||
SECTION("Construction")
|
SECTION("Construction")
|
||||||
{
|
{
|
||||||
sf::Shader movedShader = sf::Shader::createFromFile("Graphics/shader.vert", sf::Shader::Type::Vertex).value();
|
sf::Shader movedShader(std::filesystem::path("Graphics/shader.vert"), sf::Shader::Type::Vertex);
|
||||||
const sf::Shader shader = std::move(movedShader);
|
const sf::Shader shader = std::move(movedShader);
|
||||||
CHECK(shader.getNativeHandle() != 0);
|
CHECK(shader.getNativeHandle() != 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
SECTION("Assignment")
|
SECTION("Assignment")
|
||||||
{
|
{
|
||||||
sf::Shader movedShader = sf::Shader::createFromFile("Graphics/shader.vert", sf::Shader::Type::Vertex).value();
|
sf::Shader movedShader(std::filesystem::path("Graphics/shader.vert"), sf::Shader::Type::Vertex);
|
||||||
sf::Shader shader = sf::Shader::createFromFile("Graphics/shader.frag", sf::Shader::Type::Fragment).value();
|
sf::Shader shader(std::filesystem::path("Graphics/shader.frag"), sf::Shader::Type::Fragment);
|
||||||
shader = std::move(movedShader);
|
shader = std::move(movedShader);
|
||||||
CHECK(shader.getNativeHandle() != 0);
|
CHECK(shader.getNativeHandle() != 0);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -255,7 +431,7 @@ TEST_CASE("[Graphics] sf::Shader", skipShaderFullTests())
|
|||||||
{
|
{
|
||||||
sf::Shader shader;
|
sf::Shader shader;
|
||||||
CHECK(shader.loadFromMemory(vertexSource, sf::Shader::Type::Vertex) == sf::Shader::isAvailable());
|
CHECK(shader.loadFromMemory(vertexSource, sf::Shader::Type::Vertex) == sf::Shader::isAvailable());
|
||||||
CHECK_FALSE(shader.loadFromMemory(geometrySource, sf::Shader::Type::Geometry));
|
CHECK(!shader.loadFromMemory(geometrySource, sf::Shader::Type::Geometry));
|
||||||
CHECK(shader.loadFromMemory(fragmentSource, sf::Shader::Type::Fragment) == sf::Shader::isAvailable());
|
CHECK(shader.loadFromMemory(fragmentSource, sf::Shader::Type::Fragment) == sf::Shader::isAvailable());
|
||||||
CHECK(shader.loadFromMemory(vertexSource, fragmentSource) == sf::Shader::isAvailable());
|
CHECK(shader.loadFromMemory(vertexSource, fragmentSource) == sf::Shader::isAvailable());
|
||||||
CHECK(shader.loadFromMemory(vertexSource, geometrySource, fragmentSource) == sf::Shader::isGeometryAvailable());
|
CHECK(shader.loadFromMemory(vertexSource, geometrySource, fragmentSource) == sf::Shader::isGeometryAvailable());
|
||||||
@ -300,100 +476,4 @@ TEST_CASE("[Graphics] sf::Shader", skipShaderFullTests())
|
|||||||
CHECK(static_cast<bool>(shader.getNativeHandle()) == sf::Shader::isGeometryAvailable());
|
CHECK(static_cast<bool>(shader.getNativeHandle()) == sf::Shader::isGeometryAvailable());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
SECTION("createFromFile()")
|
|
||||||
{
|
|
||||||
SECTION("One shader")
|
|
||||||
{
|
|
||||||
CHECK(!sf::Shader::createFromFile("does-not-exist.vert", sf::Shader::Type::Vertex));
|
|
||||||
|
|
||||||
const auto vertexShader = sf::Shader::createFromFile("Graphics/shader.vert", sf::Shader::Type::Vertex);
|
|
||||||
CHECK(vertexShader.has_value() == sf::Shader::isAvailable());
|
|
||||||
if (vertexShader)
|
|
||||||
CHECK(static_cast<bool>(vertexShader->getNativeHandle()) == sf::Shader::isAvailable());
|
|
||||||
|
|
||||||
const auto fragmentShader = sf::Shader::createFromFile("Graphics/shader.frag", sf::Shader::Type::Fragment);
|
|
||||||
CHECK(fragmentShader.has_value() == sf::Shader::isAvailable());
|
|
||||||
if (fragmentShader)
|
|
||||||
CHECK(static_cast<bool>(fragmentShader->getNativeHandle()) == sf::Shader::isAvailable());
|
|
||||||
}
|
|
||||||
|
|
||||||
SECTION("Two shaders")
|
|
||||||
{
|
|
||||||
CHECK(!sf::Shader::createFromFile("does-not-exist.vert", "Graphics/shader.frag"));
|
|
||||||
CHECK(!sf::Shader::createFromFile("Graphics/shader.vert", "does-not-exist.frag"));
|
|
||||||
|
|
||||||
const auto shader = sf::Shader::createFromFile("Graphics/shader.vert", "Graphics/shader.frag");
|
|
||||||
CHECK(shader.has_value() == sf::Shader::isAvailable());
|
|
||||||
if (shader)
|
|
||||||
CHECK(static_cast<bool>(shader->getNativeHandle()) == sf::Shader::isAvailable());
|
|
||||||
}
|
|
||||||
|
|
||||||
SECTION("Three shaders")
|
|
||||||
{
|
|
||||||
CHECK(!sf::Shader::createFromFile("does-not-exist.vert", "Graphics/shader.geom", "Graphics/shader.frag"));
|
|
||||||
CHECK(!sf::Shader::createFromFile("Graphics/shader.vert", "does-not-exist.geom", "Graphics/shader.frag"));
|
|
||||||
CHECK(!sf::Shader::createFromFile("Graphics/shader.vert", "Graphics/shader.geom", "does-not-exist.frag"));
|
|
||||||
|
|
||||||
const auto shader = sf::Shader::createFromFile("Graphics/shader.vert",
|
|
||||||
"Graphics/shader.geom",
|
|
||||||
"Graphics/shader.frag");
|
|
||||||
CHECK(shader.has_value() == sf::Shader::isGeometryAvailable());
|
|
||||||
if (shader)
|
|
||||||
CHECK(static_cast<bool>(shader->getNativeHandle()) == sf::Shader::isGeometryAvailable());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
SECTION("createFromMemory()")
|
|
||||||
{
|
|
||||||
CHECK(sf::Shader::createFromMemory(vertexSource, sf::Shader::Type::Vertex).has_value() ==
|
|
||||||
sf::Shader::isAvailable());
|
|
||||||
CHECK(!sf::Shader::createFromMemory(geometrySource, sf::Shader::Type::Geometry));
|
|
||||||
CHECK(sf::Shader::createFromMemory(fragmentSource, sf::Shader::Type::Fragment).has_value() ==
|
|
||||||
sf::Shader::isAvailable());
|
|
||||||
CHECK(sf::Shader::createFromMemory(vertexSource, fragmentSource).has_value() == sf::Shader::isAvailable());
|
|
||||||
|
|
||||||
const auto shader = sf::Shader::createFromMemory(vertexSource, geometrySource, fragmentSource);
|
|
||||||
CHECK(shader.has_value() == sf::Shader::isGeometryAvailable());
|
|
||||||
if (shader)
|
|
||||||
CHECK(static_cast<bool>(shader->getNativeHandle()) == sf::Shader::isAvailable());
|
|
||||||
}
|
|
||||||
|
|
||||||
SECTION("createFromStream()")
|
|
||||||
{
|
|
||||||
auto vertexShaderStream = sf::FileInputStream::create("Graphics/shader.vert").value();
|
|
||||||
auto fragmentShaderStream = sf::FileInputStream::create("Graphics/shader.frag").value();
|
|
||||||
auto geometryShaderStream = sf::FileInputStream::create("Graphics/shader.geom").value();
|
|
||||||
|
|
||||||
auto emptyStream = sf::FileInputStream::create("Graphics/invalid_shader.vert").value();
|
|
||||||
|
|
||||||
SECTION("One shader")
|
|
||||||
{
|
|
||||||
CHECK(!sf::Shader::createFromStream(emptyStream, sf::Shader::Type::Vertex));
|
|
||||||
CHECK(sf::Shader::createFromStream(vertexShaderStream, sf::Shader::Type::Vertex).has_value() ==
|
|
||||||
sf::Shader::isAvailable());
|
|
||||||
CHECK(sf::Shader::createFromStream(fragmentShaderStream, sf::Shader::Type::Fragment).has_value() ==
|
|
||||||
sf::Shader::isAvailable());
|
|
||||||
}
|
|
||||||
|
|
||||||
SECTION("Two shaders")
|
|
||||||
{
|
|
||||||
CHECK(!sf::Shader::createFromStream(emptyStream, fragmentShaderStream));
|
|
||||||
CHECK(!sf::Shader::createFromStream(vertexShaderStream, emptyStream));
|
|
||||||
CHECK(sf::Shader::createFromStream(vertexShaderStream, fragmentShaderStream).has_value() ==
|
|
||||||
sf::Shader::isAvailable());
|
|
||||||
}
|
|
||||||
|
|
||||||
SECTION("Three shaders")
|
|
||||||
{
|
|
||||||
CHECK(!sf::Shader::createFromStream(emptyStream, geometryShaderStream, fragmentShaderStream));
|
|
||||||
CHECK(!sf::Shader::createFromStream(vertexShaderStream, emptyStream, fragmentShaderStream));
|
|
||||||
CHECK(!sf::Shader::createFromStream(vertexShaderStream, geometryShaderStream, emptyStream));
|
|
||||||
|
|
||||||
const auto shader = sf::Shader::createFromStream(vertexShaderStream, geometryShaderStream, fragmentShaderStream);
|
|
||||||
CHECK(shader.has_value() == sf::Shader::isGeometryAvailable());
|
|
||||||
if (shader)
|
|
||||||
CHECK(static_cast<bool>(shader->getNativeHandle()) == sf::Shader::isGeometryAvailable());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
@ -66,8 +66,8 @@ TEST_CASE("[Graphics] sf::Shape", runDisplayTests())
|
|||||||
|
|
||||||
SECTION("Set/get texture")
|
SECTION("Set/get texture")
|
||||||
{
|
{
|
||||||
const auto texture = sf::Texture::create({64, 64}).value();
|
const sf::Texture texture(sf::Vector2u(64, 64));
|
||||||
TriangleShape triangleShape({});
|
TriangleShape triangleShape({});
|
||||||
triangleShape.setTexture(&texture, true);
|
triangleShape.setTexture(&texture, true);
|
||||||
CHECK(triangleShape.getTexture() == &texture);
|
CHECK(triangleShape.getTexture() == &texture);
|
||||||
}
|
}
|
||||||
|
@ -22,7 +22,7 @@ TEST_CASE("[Graphics] sf::Sprite", runDisplayTests())
|
|||||||
STATIC_CHECK(std::is_nothrow_move_assignable_v<sf::Sprite>);
|
STATIC_CHECK(std::is_nothrow_move_assignable_v<sf::Sprite>);
|
||||||
}
|
}
|
||||||
|
|
||||||
const auto texture = sf::Texture::create({64, 64}).value();
|
const sf::Texture texture(sf::Vector2u(64, 64));
|
||||||
|
|
||||||
SECTION("Construction")
|
SECTION("Construction")
|
||||||
{
|
{
|
||||||
@ -60,7 +60,7 @@ TEST_CASE("[Graphics] sf::Sprite", runDisplayTests())
|
|||||||
SECTION("Set/get texture")
|
SECTION("Set/get texture")
|
||||||
{
|
{
|
||||||
sf::Sprite sprite(texture);
|
sf::Sprite sprite(texture);
|
||||||
const sf::Texture otherTexture = sf::Texture::create({64, 64}).value();
|
const sf::Texture otherTexture(sf::Vector2u(64, 64));
|
||||||
sprite.setTexture(otherTexture);
|
sprite.setTexture(otherTexture);
|
||||||
CHECK(&sprite.getTexture() == &otherTexture);
|
CHECK(&sprite.getTexture() == &otherTexture);
|
||||||
}
|
}
|
||||||
|
@ -21,7 +21,7 @@ TEST_CASE("[Graphics] sf::Text", runDisplayTests())
|
|||||||
STATIC_CHECK(std::is_nothrow_move_assignable_v<sf::Text>);
|
STATIC_CHECK(std::is_nothrow_move_assignable_v<sf::Text>);
|
||||||
}
|
}
|
||||||
|
|
||||||
const auto font = sf::Font::createFromFile("Graphics/tuffy.ttf").value();
|
const sf::Font font("Graphics/tuffy.ttf");
|
||||||
|
|
||||||
SECTION("Construction")
|
SECTION("Construction")
|
||||||
{
|
{
|
||||||
@ -86,8 +86,8 @@ TEST_CASE("[Graphics] sf::Text", runDisplayTests())
|
|||||||
|
|
||||||
SECTION("Set/get font")
|
SECTION("Set/get font")
|
||||||
{
|
{
|
||||||
sf::Text text(font);
|
sf::Text text(font);
|
||||||
const auto otherFont = sf::Font::createFromFile("Graphics/tuffy.ttf").value();
|
const sf::Font otherFont("Graphics/tuffy.ttf");
|
||||||
text.setFont(otherFont);
|
text.setFont(otherFont);
|
||||||
CHECK(&text.getFont() == &otherFont);
|
CHECK(&text.getFont() == &otherFont);
|
||||||
}
|
}
|
||||||
|
@ -24,12 +24,99 @@ TEST_CASE("[Graphics] sf::Texture", runDisplayTests())
|
|||||||
|
|
||||||
SECTION("Construction")
|
SECTION("Construction")
|
||||||
{
|
{
|
||||||
const sf::Texture texture;
|
SECTION("Default constructor")
|
||||||
CHECK(texture.getSize() == sf::Vector2u());
|
{
|
||||||
CHECK(!texture.isSmooth());
|
const sf::Texture texture;
|
||||||
CHECK(!texture.isSrgb());
|
CHECK(texture.getSize() == sf::Vector2u());
|
||||||
CHECK(!texture.isRepeated());
|
CHECK(!texture.isSmooth());
|
||||||
CHECK(texture.getNativeHandle() == 0);
|
CHECK(!texture.isSrgb());
|
||||||
|
CHECK(!texture.isRepeated());
|
||||||
|
CHECK(texture.getNativeHandle() == 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
SECTION("Vector")
|
||||||
|
{
|
||||||
|
SECTION("At least one zero dimension")
|
||||||
|
{
|
||||||
|
CHECK_THROWS_AS(sf::Texture(sf::Vector2u()), std::runtime_error);
|
||||||
|
CHECK_THROWS_AS(sf::Texture(sf::Vector2u(0, 1)), std::runtime_error);
|
||||||
|
CHECK_THROWS_AS(sf::Texture(sf::Vector2u(1, 0)), std::runtime_error);
|
||||||
|
}
|
||||||
|
|
||||||
|
SECTION("Valid size")
|
||||||
|
{
|
||||||
|
const sf::Texture texture(sf::Vector2u(100, 100));
|
||||||
|
CHECK(texture.getSize() == sf::Vector2u(100, 100));
|
||||||
|
CHECK(texture.getNativeHandle() != 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
SECTION("Too large")
|
||||||
|
{
|
||||||
|
CHECK_THROWS_AS(sf::Texture(sf::Vector2u(100'000, 100'000)), std::runtime_error);
|
||||||
|
CHECK_THROWS_AS(sf::Texture(sf::Vector2u(1'000'000, 1'000'000)), std::runtime_error);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
SECTION("File")
|
||||||
|
{
|
||||||
|
const sf::Texture texture("Graphics/sfml-logo-big.png");
|
||||||
|
CHECK(texture.getSize() == sf::Vector2u(1001, 304));
|
||||||
|
CHECK(!texture.isSmooth());
|
||||||
|
CHECK(!texture.isSrgb());
|
||||||
|
CHECK(!texture.isRepeated());
|
||||||
|
CHECK(texture.getNativeHandle() != 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
SECTION("Memory")
|
||||||
|
{
|
||||||
|
const auto memory = loadIntoMemory("Graphics/sfml-logo-big.png");
|
||||||
|
const sf::Texture texture(memory.data(), memory.size());
|
||||||
|
CHECK(texture.getSize() == sf::Vector2u(1001, 304));
|
||||||
|
CHECK(!texture.isSmooth());
|
||||||
|
CHECK(!texture.isSrgb());
|
||||||
|
CHECK(!texture.isRepeated());
|
||||||
|
CHECK(texture.getNativeHandle() != 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
SECTION("Stream")
|
||||||
|
{
|
||||||
|
sf::FileInputStream stream("Graphics/sfml-logo-big.png");
|
||||||
|
const sf::Texture texture(stream);
|
||||||
|
CHECK(texture.getSize() == sf::Vector2u(1001, 304));
|
||||||
|
CHECK(!texture.isSmooth());
|
||||||
|
CHECK(!texture.isSrgb());
|
||||||
|
CHECK(!texture.isRepeated());
|
||||||
|
CHECK(texture.getNativeHandle() != 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
SECTION("Image")
|
||||||
|
{
|
||||||
|
SECTION("Subarea of image")
|
||||||
|
{
|
||||||
|
const sf::Image image(sf::Vector2u(10, 15));
|
||||||
|
|
||||||
|
SECTION("Non-truncated area")
|
||||||
|
{
|
||||||
|
const sf::Texture texture(image, false, {{0, 0}, {5, 10}});
|
||||||
|
CHECK(texture.getSize() == sf::Vector2u(5, 10));
|
||||||
|
CHECK(texture.getNativeHandle() != 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
SECTION("Truncated area (negative position)")
|
||||||
|
{
|
||||||
|
const sf::Texture texture(image, false, {{-5, -5}, {4, 8}});
|
||||||
|
CHECK(texture.getSize() == sf::Vector2u(4, 8));
|
||||||
|
CHECK(texture.getNativeHandle() != 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
SECTION("Truncated area (width/height too big)")
|
||||||
|
{
|
||||||
|
const sf::Texture texture(image, false, {{5, 5}, {12, 18}});
|
||||||
|
CHECK(texture.getSize() == sf::Vector2u(5, 10));
|
||||||
|
CHECK(texture.getNativeHandle() != 0);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
SECTION("Move semantics")
|
SECTION("Move semantics")
|
||||||
@ -58,12 +145,12 @@ TEST_CASE("[Graphics] sf::Texture", runDisplayTests())
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
SECTION("Move semantics (create)")
|
SECTION("Move semantics")
|
||||||
{
|
{
|
||||||
SECTION("Construction")
|
SECTION("Construction")
|
||||||
{
|
{
|
||||||
sf::Texture movedTexture = sf::Texture::create({64, 64}).value();
|
sf::Texture movedTexture(sf::Vector2u(64, 64));
|
||||||
const sf::Texture texture = std::move(movedTexture);
|
const sf::Texture texture = std::move(movedTexture);
|
||||||
CHECK(texture.getSize() == sf::Vector2u(64, 64));
|
CHECK(texture.getSize() == sf::Vector2u(64, 64));
|
||||||
CHECK(!texture.isSmooth());
|
CHECK(!texture.isSmooth());
|
||||||
CHECK(!texture.isSrgb());
|
CHECK(!texture.isSrgb());
|
||||||
@ -73,9 +160,9 @@ TEST_CASE("[Graphics] sf::Texture", runDisplayTests())
|
|||||||
|
|
||||||
SECTION("Assignment")
|
SECTION("Assignment")
|
||||||
{
|
{
|
||||||
sf::Texture movedTexture = sf::Texture::create({64, 64}).value();
|
sf::Texture movedTexture(sf::Vector2u(64, 64));
|
||||||
sf::Texture texture = sf::Texture::create({128, 128}).value();
|
sf::Texture texture(sf::Vector2u(128, 128));
|
||||||
texture = std::move(movedTexture);
|
texture = std::move(movedTexture);
|
||||||
CHECK(texture.getSize() == sf::Vector2u(64, 64));
|
CHECK(texture.getSize() == sf::Vector2u(64, 64));
|
||||||
CHECK(!texture.isSmooth());
|
CHECK(!texture.isSmooth());
|
||||||
CHECK(!texture.isSrgb());
|
CHECK(!texture.isSrgb());
|
||||||
@ -84,29 +171,6 @@ TEST_CASE("[Graphics] sf::Texture", runDisplayTests())
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
SECTION("create()")
|
|
||||||
{
|
|
||||||
SECTION("At least one zero dimension")
|
|
||||||
{
|
|
||||||
CHECK(!sf::Texture::create({}));
|
|
||||||
CHECK(!sf::Texture::create({0, 1}));
|
|
||||||
CHECK(!sf::Texture::create({1, 0}));
|
|
||||||
}
|
|
||||||
|
|
||||||
SECTION("Valid size")
|
|
||||||
{
|
|
||||||
const auto texture = sf::Texture::create({100, 100}).value();
|
|
||||||
CHECK(texture.getSize() == sf::Vector2u(100, 100));
|
|
||||||
CHECK(texture.getNativeHandle() != 0);
|
|
||||||
}
|
|
||||||
|
|
||||||
SECTION("Too large")
|
|
||||||
{
|
|
||||||
CHECK(!sf::Texture::create({100'000, 100'000}));
|
|
||||||
CHECK(!sf::Texture::create({1'000'000, 1'000'000}));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
SECTION("resize()")
|
SECTION("resize()")
|
||||||
{
|
{
|
||||||
sf::Texture texture;
|
sf::Texture texture;
|
||||||
@ -206,72 +270,11 @@ TEST_CASE("[Graphics] sf::Texture", runDisplayTests())
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
SECTION("createFromFile()")
|
|
||||||
{
|
|
||||||
const auto texture = sf::Texture::createFromFile("Graphics/sfml-logo-big.png").value();
|
|
||||||
CHECK(texture.getSize() == sf::Vector2u(1001, 304));
|
|
||||||
CHECK(!texture.isSmooth());
|
|
||||||
CHECK(!texture.isSrgb());
|
|
||||||
CHECK(!texture.isRepeated());
|
|
||||||
CHECK(texture.getNativeHandle() != 0);
|
|
||||||
}
|
|
||||||
|
|
||||||
SECTION("createFromMemory()")
|
|
||||||
{
|
|
||||||
const auto memory = loadIntoMemory("Graphics/sfml-logo-big.png");
|
|
||||||
const auto texture = sf::Texture::createFromMemory(memory.data(), memory.size()).value();
|
|
||||||
CHECK(texture.getSize() == sf::Vector2u(1001, 304));
|
|
||||||
CHECK(!texture.isSmooth());
|
|
||||||
CHECK(!texture.isSrgb());
|
|
||||||
CHECK(!texture.isRepeated());
|
|
||||||
CHECK(texture.getNativeHandle() != 0);
|
|
||||||
}
|
|
||||||
|
|
||||||
SECTION("createFromStream()")
|
|
||||||
{
|
|
||||||
auto stream = sf::FileInputStream::create("Graphics/sfml-logo-big.png").value();
|
|
||||||
const auto texture = sf::Texture::createFromStream(stream).value();
|
|
||||||
CHECK(texture.getSize() == sf::Vector2u(1001, 304));
|
|
||||||
CHECK(!texture.isSmooth());
|
|
||||||
CHECK(!texture.isSrgb());
|
|
||||||
CHECK(!texture.isRepeated());
|
|
||||||
CHECK(texture.getNativeHandle() != 0);
|
|
||||||
}
|
|
||||||
|
|
||||||
SECTION("createFromImage()")
|
|
||||||
{
|
|
||||||
SECTION("Subarea of image")
|
|
||||||
{
|
|
||||||
const sf::Image image(sf::Vector2u(10, 15));
|
|
||||||
|
|
||||||
SECTION("Non-truncated area")
|
|
||||||
{
|
|
||||||
const auto texture = sf::Texture::createFromImage(image, false, {{0, 0}, {5, 10}}).value();
|
|
||||||
CHECK(texture.getSize() == sf::Vector2u(5, 10));
|
|
||||||
CHECK(texture.getNativeHandle() != 0);
|
|
||||||
}
|
|
||||||
|
|
||||||
SECTION("Truncated area (negative position)")
|
|
||||||
{
|
|
||||||
const auto texture = sf::Texture::createFromImage(image, false, {{-5, -5}, {4, 8}}).value();
|
|
||||||
CHECK(texture.getSize() == sf::Vector2u(4, 8));
|
|
||||||
CHECK(texture.getNativeHandle() != 0);
|
|
||||||
}
|
|
||||||
|
|
||||||
SECTION("Truncated area (width/height too big)")
|
|
||||||
{
|
|
||||||
const auto texture = sf::Texture::createFromImage(image, false, {{5, 5}, {12, 18}}).value();
|
|
||||||
CHECK(texture.getSize() == sf::Vector2u(5, 10));
|
|
||||||
CHECK(texture.getNativeHandle() != 0);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
SECTION("Copy semantics")
|
SECTION("Copy semantics")
|
||||||
{
|
{
|
||||||
constexpr std::uint8_t red[] = {0xFF, 0x00, 0x00, 0xFF, 0xFF, 0x00, 0x00, 0xFF};
|
constexpr std::uint8_t red[] = {0xFF, 0x00, 0x00, 0xFF, 0xFF, 0x00, 0x00, 0xFF};
|
||||||
|
|
||||||
auto texture = sf::Texture::create({1, 2}).value();
|
sf::Texture texture(sf::Vector2u(1, 2));
|
||||||
texture.update(red);
|
texture.update(red);
|
||||||
|
|
||||||
SECTION("Construction")
|
SECTION("Construction")
|
||||||
@ -283,8 +286,8 @@ TEST_CASE("[Graphics] sf::Texture", runDisplayTests())
|
|||||||
|
|
||||||
SECTION("Assignment")
|
SECTION("Assignment")
|
||||||
{
|
{
|
||||||
sf::Texture textureCopy = sf::Texture::create({64, 64}).value();
|
sf::Texture textureCopy(sf::Vector2u(64, 64));
|
||||||
textureCopy = texture;
|
textureCopy = texture;
|
||||||
REQUIRE(textureCopy.getSize() == sf::Vector2u(1, 2));
|
REQUIRE(textureCopy.getSize() == sf::Vector2u(1, 2));
|
||||||
CHECK(textureCopy.copyToImage().getPixel(sf::Vector2u(0, 1)) == sf::Color::Red);
|
CHECK(textureCopy.copyToImage().getPixel(sf::Vector2u(0, 1)) == sf::Color::Red);
|
||||||
}
|
}
|
||||||
@ -297,14 +300,14 @@ TEST_CASE("[Graphics] sf::Texture", runDisplayTests())
|
|||||||
|
|
||||||
SECTION("Pixels")
|
SECTION("Pixels")
|
||||||
{
|
{
|
||||||
auto texture = sf::Texture::create(sf::Vector2u(1, 1)).value();
|
sf::Texture texture(sf::Vector2u(1, 1));
|
||||||
texture.update(yellow);
|
texture.update(yellow);
|
||||||
CHECK(texture.copyToImage().getPixel(sf::Vector2u(0, 0)) == sf::Color::Yellow);
|
CHECK(texture.copyToImage().getPixel(sf::Vector2u(0, 0)) == sf::Color::Yellow);
|
||||||
}
|
}
|
||||||
|
|
||||||
SECTION("Pixels, size and destination")
|
SECTION("Pixels, size and destination")
|
||||||
{
|
{
|
||||||
auto texture = sf::Texture::create(sf::Vector2u(2, 1)).value();
|
sf::Texture texture(sf::Vector2u(2, 1));
|
||||||
texture.update(yellow, sf::Vector2u(1, 1), sf::Vector2u(0, 0));
|
texture.update(yellow, sf::Vector2u(1, 1), sf::Vector2u(0, 0));
|
||||||
texture.update(cyan, sf::Vector2u(1, 1), sf::Vector2u(1, 0));
|
texture.update(cyan, sf::Vector2u(1, 1), sf::Vector2u(1, 0));
|
||||||
CHECK(texture.copyToImage().getPixel(sf::Vector2u(0, 0)) == sf::Color::Yellow);
|
CHECK(texture.copyToImage().getPixel(sf::Vector2u(0, 0)) == sf::Color::Yellow);
|
||||||
@ -313,19 +316,19 @@ TEST_CASE("[Graphics] sf::Texture", runDisplayTests())
|
|||||||
|
|
||||||
SECTION("Another texture")
|
SECTION("Another texture")
|
||||||
{
|
{
|
||||||
auto otherTexture = sf::Texture::create(sf::Vector2u(1, 1)).value();
|
sf::Texture otherTexture(sf::Vector2u(1, 1));
|
||||||
otherTexture.update(cyan);
|
otherTexture.update(cyan);
|
||||||
auto texture = sf::Texture::create(sf::Vector2u(1, 1)).value();
|
sf::Texture texture(sf::Vector2u(1, 1));
|
||||||
texture.update(otherTexture);
|
texture.update(otherTexture);
|
||||||
CHECK(texture.copyToImage().getPixel(sf::Vector2u(0, 0)) == sf::Color::Cyan);
|
CHECK(texture.copyToImage().getPixel(sf::Vector2u(0, 0)) == sf::Color::Cyan);
|
||||||
}
|
}
|
||||||
|
|
||||||
SECTION("Another texture and destination")
|
SECTION("Another texture and destination")
|
||||||
{
|
{
|
||||||
auto texture = sf::Texture::create(sf::Vector2u(2, 1)).value();
|
sf::Texture texture(sf::Vector2u(2, 1));
|
||||||
auto otherTexture1 = sf::Texture::create(sf::Vector2u(1, 1)).value();
|
sf::Texture otherTexture1(sf::Vector2u(1, 1));
|
||||||
otherTexture1.update(cyan);
|
otherTexture1.update(cyan);
|
||||||
auto otherTexture2 = sf::Texture::create(sf::Vector2u(1, 1)).value();
|
sf::Texture otherTexture2(sf::Vector2u(1, 1));
|
||||||
otherTexture2.update(yellow);
|
otherTexture2.update(yellow);
|
||||||
texture.update(otherTexture1, sf::Vector2u(0, 0));
|
texture.update(otherTexture1, sf::Vector2u(0, 0));
|
||||||
texture.update(otherTexture2, sf::Vector2u(1, 0));
|
texture.update(otherTexture2, sf::Vector2u(1, 0));
|
||||||
@ -335,7 +338,7 @@ TEST_CASE("[Graphics] sf::Texture", runDisplayTests())
|
|||||||
|
|
||||||
SECTION("Image")
|
SECTION("Image")
|
||||||
{
|
{
|
||||||
auto texture = sf::Texture::create(sf::Vector2u(16, 32)).value();
|
sf::Texture texture(sf::Vector2u(16, 32));
|
||||||
const sf::Image image(sf::Vector2u(16, 32), sf::Color::Red);
|
const sf::Image image(sf::Vector2u(16, 32), sf::Color::Red);
|
||||||
texture.update(image);
|
texture.update(image);
|
||||||
CHECK(texture.copyToImage().getPixel(sf::Vector2u(7, 15)) == sf::Color::Red);
|
CHECK(texture.copyToImage().getPixel(sf::Vector2u(7, 15)) == sf::Color::Red);
|
||||||
@ -343,7 +346,7 @@ TEST_CASE("[Graphics] sf::Texture", runDisplayTests())
|
|||||||
|
|
||||||
SECTION("Image and destination")
|
SECTION("Image and destination")
|
||||||
{
|
{
|
||||||
auto texture = sf::Texture::create(sf::Vector2u(16, 32)).value();
|
sf::Texture texture(sf::Vector2u(16, 32));
|
||||||
const sf::Image image1(sf::Vector2u(16, 16), sf::Color::Red);
|
const sf::Image image1(sf::Vector2u(16, 16), sf::Color::Red);
|
||||||
texture.update(image1);
|
texture.update(image1);
|
||||||
const sf::Image image2(sf::Vector2u(16, 16), sf::Color::Green);
|
const sf::Image image2(sf::Vector2u(16, 16), sf::Color::Green);
|
||||||
@ -356,7 +359,7 @@ TEST_CASE("[Graphics] sf::Texture", runDisplayTests())
|
|||||||
|
|
||||||
SECTION("Set/get smooth")
|
SECTION("Set/get smooth")
|
||||||
{
|
{
|
||||||
sf::Texture texture = sf::Texture::create({64, 64}).value();
|
sf::Texture texture(sf::Vector2u(64, 64));
|
||||||
CHECK(!texture.isSmooth());
|
CHECK(!texture.isSmooth());
|
||||||
texture.setSmooth(true);
|
texture.setSmooth(true);
|
||||||
CHECK(texture.isSmooth());
|
CHECK(texture.isSmooth());
|
||||||
@ -366,7 +369,7 @@ TEST_CASE("[Graphics] sf::Texture", runDisplayTests())
|
|||||||
|
|
||||||
SECTION("Set/get repeated")
|
SECTION("Set/get repeated")
|
||||||
{
|
{
|
||||||
sf::Texture texture = sf::Texture::create({64, 64}).value();
|
sf::Texture texture(sf::Vector2u(64, 64));
|
||||||
CHECK(!texture.isRepeated());
|
CHECK(!texture.isRepeated());
|
||||||
texture.setRepeated(true);
|
texture.setRepeated(true);
|
||||||
CHECK(texture.isRepeated());
|
CHECK(texture.isRepeated());
|
||||||
@ -376,7 +379,7 @@ TEST_CASE("[Graphics] sf::Texture", runDisplayTests())
|
|||||||
|
|
||||||
SECTION("generateMipmap()")
|
SECTION("generateMipmap()")
|
||||||
{
|
{
|
||||||
sf::Texture texture = sf::Texture::create({100, 100}).value();
|
sf::Texture texture(sf::Vector2u(100, 100));
|
||||||
CHECK(texture.generateMipmap());
|
CHECK(texture.generateMipmap());
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -385,12 +388,12 @@ TEST_CASE("[Graphics] sf::Texture", runDisplayTests())
|
|||||||
constexpr std::uint8_t blue[] = {0x00, 0x00, 0xFF, 0xFF};
|
constexpr std::uint8_t blue[] = {0x00, 0x00, 0xFF, 0xFF};
|
||||||
constexpr std::uint8_t green[] = {0x00, 0xFF, 0x00, 0xFF, 0x00, 0xFF, 0x00, 0xFF};
|
constexpr std::uint8_t green[] = {0x00, 0xFF, 0x00, 0xFF, 0x00, 0xFF, 0x00, 0xFF};
|
||||||
|
|
||||||
auto texture1 = sf::Texture::create(sf::Vector2u(1, 1), true).value();
|
sf::Texture texture1(sf::Vector2u(1, 1), true);
|
||||||
texture1.update(blue);
|
texture1.update(blue);
|
||||||
texture1.setSmooth(false);
|
texture1.setSmooth(false);
|
||||||
texture1.setRepeated(true);
|
texture1.setRepeated(true);
|
||||||
|
|
||||||
auto texture2 = sf::Texture::create(sf::Vector2u(2, 1), false).value();
|
sf::Texture texture2(sf::Vector2u(2, 1), false);
|
||||||
texture2.update(green);
|
texture2.update(green);
|
||||||
texture2.setSmooth(true);
|
texture2.setSmooth(true);
|
||||||
texture2.setRepeated(false);
|
texture2.setRepeated(false);
|
||||||
|
@ -72,24 +72,38 @@ TEST_CASE("[System] sf::FileInputStream")
|
|||||||
STATIC_CHECK(std::is_nothrow_move_assignable_v<sf::FileInputStream>);
|
STATIC_CHECK(std::is_nothrow_move_assignable_v<sf::FileInputStream>);
|
||||||
}
|
}
|
||||||
|
|
||||||
SECTION("Default constructor")
|
|
||||||
{
|
|
||||||
sf::FileInputStream fileInputStream;
|
|
||||||
CHECK(fileInputStream.read(nullptr, 0) == std::nullopt);
|
|
||||||
CHECK(fileInputStream.seek(0) == std::nullopt);
|
|
||||||
CHECK(fileInputStream.tell() == std::nullopt);
|
|
||||||
CHECK(fileInputStream.getSize() == std::nullopt);
|
|
||||||
}
|
|
||||||
|
|
||||||
const TemporaryFile temporaryFile("Hello world");
|
const TemporaryFile temporaryFile("Hello world");
|
||||||
char buffer[32];
|
char buffer[32];
|
||||||
|
|
||||||
|
SECTION("Construction")
|
||||||
|
{
|
||||||
|
SECTION("Default constructor")
|
||||||
|
{
|
||||||
|
sf::FileInputStream fileInputStream;
|
||||||
|
CHECK(fileInputStream.read(nullptr, 0) == std::nullopt);
|
||||||
|
CHECK(fileInputStream.seek(0) == std::nullopt);
|
||||||
|
CHECK(fileInputStream.tell() == std::nullopt);
|
||||||
|
CHECK(fileInputStream.getSize() == std::nullopt);
|
||||||
|
}
|
||||||
|
|
||||||
|
SECTION("File path constructor")
|
||||||
|
{
|
||||||
|
sf::FileInputStream fileInputStream(temporaryFile.getPath());
|
||||||
|
CHECK(fileInputStream.read(buffer, 5) == 5);
|
||||||
|
CHECK(fileInputStream.tell() == 5);
|
||||||
|
CHECK(fileInputStream.getSize() == 11);
|
||||||
|
CHECK(std::string_view(buffer, 5) == "Hello"sv);
|
||||||
|
CHECK(fileInputStream.seek(6) == 6);
|
||||||
|
CHECK(fileInputStream.tell() == 6);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
SECTION("Move semantics")
|
SECTION("Move semantics")
|
||||||
{
|
{
|
||||||
SECTION("Move constructor")
|
SECTION("Move constructor")
|
||||||
{
|
{
|
||||||
auto movedFileInputStream = sf::FileInputStream::create(temporaryFile.getPath()).value();
|
sf::FileInputStream movedFileInputStream(temporaryFile.getPath());
|
||||||
sf::FileInputStream fileInputStream = std::move(movedFileInputStream);
|
sf::FileInputStream fileInputStream = std::move(movedFileInputStream);
|
||||||
CHECK(fileInputStream.read(buffer, 6) == 6);
|
CHECK(fileInputStream.read(buffer, 6) == 6);
|
||||||
CHECK(fileInputStream.tell() == 6);
|
CHECK(fileInputStream.tell() == 6);
|
||||||
CHECK(fileInputStream.getSize() == 11);
|
CHECK(fileInputStream.getSize() == 11);
|
||||||
@ -98,10 +112,10 @@ TEST_CASE("[System] sf::FileInputStream")
|
|||||||
|
|
||||||
SECTION("Move assignment")
|
SECTION("Move assignment")
|
||||||
{
|
{
|
||||||
auto movedFileInputStream = sf::FileInputStream::create(temporaryFile.getPath()).value();
|
sf::FileInputStream movedFileInputStream(temporaryFile.getPath());
|
||||||
const TemporaryFile temporaryFile2("Hello world the sequel");
|
const TemporaryFile temporaryFile2("Hello world the sequel");
|
||||||
auto fileInputStream = sf::FileInputStream::create(temporaryFile2.getPath()).value();
|
sf::FileInputStream fileInputStream(temporaryFile2.getPath());
|
||||||
fileInputStream = std::move(movedFileInputStream);
|
fileInputStream = std::move(movedFileInputStream);
|
||||||
CHECK(fileInputStream.read(buffer, 6) == 6);
|
CHECK(fileInputStream.read(buffer, 6) == 6);
|
||||||
CHECK(fileInputStream.tell() == 6);
|
CHECK(fileInputStream.tell() == 6);
|
||||||
CHECK(fileInputStream.getSize() == 11);
|
CHECK(fileInputStream.getSize() == 11);
|
||||||
@ -123,7 +137,7 @@ TEST_CASE("[System] sf::FileInputStream")
|
|||||||
|
|
||||||
SECTION("Temporary file stream create")
|
SECTION("Temporary file stream create")
|
||||||
{
|
{
|
||||||
auto fileInputStream = sf::FileInputStream::create(temporaryFile.getPath()).value();
|
sf::FileInputStream fileInputStream(temporaryFile.getPath());
|
||||||
CHECK(fileInputStream.read(buffer, 5) == 5);
|
CHECK(fileInputStream.read(buffer, 5) == 5);
|
||||||
CHECK(fileInputStream.tell() == 5);
|
CHECK(fileInputStream.tell() == 5);
|
||||||
CHECK(fileInputStream.getSize() == 11);
|
CHECK(fileInputStream.getSize() == 11);
|
||||||
|
@ -18,8 +18,17 @@ TEST_CASE("[System] sf::MemoryInputStream")
|
|||||||
|
|
||||||
using namespace std::literals::string_view_literals;
|
using namespace std::literals::string_view_literals;
|
||||||
|
|
||||||
SECTION("open()")
|
SECTION("Construction")
|
||||||
{
|
{
|
||||||
|
SECTION("Null data")
|
||||||
|
{
|
||||||
|
sf::MemoryInputStream memoryInputStream(nullptr, 0);
|
||||||
|
CHECK(memoryInputStream.read(nullptr, 0) == std::nullopt);
|
||||||
|
CHECK(memoryInputStream.seek(0) == std::nullopt);
|
||||||
|
CHECK(memoryInputStream.tell() == std::nullopt);
|
||||||
|
CHECK(memoryInputStream.getSize() == std::nullopt);
|
||||||
|
}
|
||||||
|
|
||||||
static constexpr auto input = "hello world"sv;
|
static constexpr auto input = "hello world"sv;
|
||||||
|
|
||||||
SECTION("Zero length")
|
SECTION("Zero length")
|
||||||
|
@ -17,6 +17,37 @@ TEST_CASE("[Window] sf::Cursor", runDisplayTests())
|
|||||||
STATIC_CHECK(std::is_nothrow_move_assignable_v<sf::Cursor>);
|
STATIC_CHECK(std::is_nothrow_move_assignable_v<sf::Cursor>);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
SECTION("Constructor")
|
||||||
|
{
|
||||||
|
SECTION("Pixels")
|
||||||
|
{
|
||||||
|
static constexpr std::array<std::uint8_t, 4> pixels{};
|
||||||
|
|
||||||
|
CHECK_THROWS_AS(sf::Cursor(nullptr, {}, {}), std::runtime_error);
|
||||||
|
CHECK_THROWS_AS(sf::Cursor(pixels.data(), {0, 1}, {}), std::runtime_error);
|
||||||
|
CHECK_THROWS_AS(sf::Cursor(pixels.data(), {1, 0}, {}), std::runtime_error);
|
||||||
|
CHECK_NOTHROW(sf::Cursor(pixels.data(), {1, 1}, {}));
|
||||||
|
}
|
||||||
|
|
||||||
|
SECTION("System")
|
||||||
|
{
|
||||||
|
CHECK_NOTHROW(sf::Cursor(sf::Cursor::Type::Hand));
|
||||||
|
CHECK_NOTHROW(sf::Cursor(sf::Cursor::Type::SizeHorizontal));
|
||||||
|
CHECK_NOTHROW(sf::Cursor(sf::Cursor::Type::SizeVertical));
|
||||||
|
CHECK_NOTHROW(sf::Cursor(sf::Cursor::Type::SizeLeft));
|
||||||
|
CHECK_NOTHROW(sf::Cursor(sf::Cursor::Type::SizeRight));
|
||||||
|
CHECK_NOTHROW(sf::Cursor(sf::Cursor::Type::SizeTop));
|
||||||
|
CHECK_NOTHROW(sf::Cursor(sf::Cursor::Type::SizeBottom));
|
||||||
|
CHECK_NOTHROW(sf::Cursor(sf::Cursor::Type::SizeTopLeft));
|
||||||
|
CHECK_NOTHROW(sf::Cursor(sf::Cursor::Type::SizeTopRight));
|
||||||
|
CHECK_NOTHROW(sf::Cursor(sf::Cursor::Type::SizeBottomLeft));
|
||||||
|
CHECK_NOTHROW(sf::Cursor(sf::Cursor::Type::SizeBottomRight));
|
||||||
|
CHECK_NOTHROW(sf::Cursor(sf::Cursor::Type::Cross));
|
||||||
|
CHECK_NOTHROW(sf::Cursor(sf::Cursor::Type::Help));
|
||||||
|
CHECK_NOTHROW(sf::Cursor(sf::Cursor::Type::NotAllowed));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
SECTION("loadFromPixels()")
|
SECTION("loadFromPixels()")
|
||||||
{
|
{
|
||||||
static constexpr std::array<std::uint8_t, 4> pixels{};
|
static constexpr std::array<std::uint8_t, 4> pixels{};
|
||||||
|
@ -26,16 +26,16 @@ int main()
|
|||||||
sf::RenderWindow window(sf::VideoMode({800, 600}), "SFML window");
|
sf::RenderWindow window(sf::VideoMode({800, 600}), "SFML window");
|
||||||
|
|
||||||
// Set the Icon
|
// Set the Icon
|
||||||
const auto icon = sf::Image::loadFromFile(resourcePath() / "icon.png").value();
|
const sf::Image icon(resourcePath() / "icon.png");
|
||||||
window.setIcon(icon);
|
window.setIcon(icon);
|
||||||
|
|
||||||
// Load a sprite to display
|
// Load a sprite to display
|
||||||
const auto texture = sf::Texture::loadFromFile(resourcePath() / "background.jpg").value();
|
const sf::Texture texture(resourcePath() / "background.jpg");
|
||||||
sf::Sprite sprite(texture);
|
sf::Sprite sprite(texture);
|
||||||
|
|
||||||
// Create a graphical text to display
|
// Create a graphical text to display
|
||||||
const auto font = sf::Font::openFromFile(resourcePath() / "tuffy.ttf").value();
|
const sf::Font font(resourcePath() / "tuffy.ttf");
|
||||||
sf::Text text(font, "Hello SFML", 50);
|
sf::Text text(font, "Hello SFML", 50);
|
||||||
text.setFillColor(sf::Color::Black);
|
text.setFillColor(sf::Color::Black);
|
||||||
|
|
||||||
// Load a music to play
|
// Load a music to play
|
||||||
|
@ -24,16 +24,16 @@ int main()
|
|||||||
sf::RenderWindow window(sf::VideoMode({800, 600}), "SFML window");
|
sf::RenderWindow window(sf::VideoMode({800, 600}), "SFML window");
|
||||||
|
|
||||||
// Set the Icon
|
// Set the Icon
|
||||||
const auto icon = sf::Image::loadFromFile("icon.png").value();
|
const sf::Image icon("icon.png");
|
||||||
window.setIcon(icon);
|
window.setIcon(icon);
|
||||||
|
|
||||||
// Load a sprite to display
|
// Load a sprite to display
|
||||||
const auto texture = sf::Texture::loadFromFile("background.jpg").value();
|
const sf::Texture texture("background.jpg");
|
||||||
sf::Sprite sprite(texture);
|
sf::Sprite sprite(texture);
|
||||||
|
|
||||||
// Create a graphical text to display
|
// Create a graphical text to display
|
||||||
const auto font = sf::Font::openFromFile("tuffy.ttf").value();
|
const sf::Font font("tuffy.ttf");
|
||||||
sf::Text text(font, "Hello SFML", 50);
|
sf::Text text(font, "Hello SFML", 50);
|
||||||
text.setFillColor(sf::Color::Black);
|
text.setFillColor(sf::Color::Black);
|
||||||
|
|
||||||
// Load a music to play
|
// Load a music to play
|
||||||
|
Loading…
Reference in New Issue
Block a user