From e185f6d53ef03db69c6002b4cacfa912265bbb1e Mon Sep 17 00:00:00 2001 From: binary1248 Date: Sat, 6 Jul 2024 04:24:00 +0200 Subject: [PATCH] Replace factory functions with throwing constructors --- doc/mainpage.hpp | 6 +- examples/android/app/src/main/jni/main.cpp | 4 +- examples/cocoa/CocoaAppDelegate.mm | 4 +- examples/event_handling/EventHandling.cpp | 2 +- examples/island/Island.cpp | 23 +- examples/joystick/Joystick.cpp | 2 +- examples/opengl/OpenGL.cpp | 10 +- examples/raw_input/RawInput.cpp | 2 +- examples/shader/Shader.cpp | 75 ++-- examples/sound/Sound.cpp | 4 +- examples/sound_effects/SoundEffects.cpp | 112 +++--- examples/tennis/Tennis.cpp | 10 +- examples/vulkan/Vulkan.cpp | 23 +- examples/win32/Win32.cpp | 8 +- include/SFML/Audio/InputSoundFile.hpp | 39 +- include/SFML/Audio/Music.hpp | 80 ++-- include/SFML/Audio/OutputSoundFile.hpp | 28 +- include/SFML/Audio/Sound.hpp | 2 +- include/SFML/Audio/SoundBuffer.hpp | 95 +++-- include/SFML/Graphics/Font.hpp | 68 ++-- include/SFML/Graphics/Image.hpp | 99 +++-- include/SFML/Graphics/RenderTexture.hpp | 45 ++- include/SFML/Graphics/RenderWindow.hpp | 10 +- include/SFML/Graphics/Shader.hpp | 169 ++++---- include/SFML/Graphics/Sprite.hpp | 2 +- include/SFML/Graphics/Text.hpp | 2 +- include/SFML/Graphics/Texture.hpp | 196 +++++----- include/SFML/System/FileInputStream.hpp | 12 +- include/SFML/System/InputStream.hpp | 6 +- include/SFML/System/MemoryInputStream.hpp | 9 - include/SFML/Window/Cursor.hpp | 49 +++ include/SFML/Window/Window.hpp | 6 +- src/SFML/Audio/InputSoundFile.cpp | 60 ++- src/SFML/Audio/Music.cpp | 60 ++- src/SFML/Audio/OutputSoundFile.cpp | 27 +- src/SFML/Audio/SoundBuffer.cpp | 89 ++--- src/SFML/Audio/SoundBufferRecorder.cpp | 2 +- src/SFML/Graphics/Font.cpp | 125 +++--- src/SFML/Graphics/Image.cpp | 62 ++- src/SFML/Graphics/RenderTexture.cpp | 58 ++- src/SFML/Graphics/Shader.cpp | 363 ++++++++---------- src/SFML/Graphics/Texture.cpp | 132 ++++--- src/SFML/System/FileInputStream.cpp | 20 +- src/SFML/System/MemoryInputStream.cpp | 14 +- src/SFML/Window/Cursor.cpp | 19 + test/Audio/InputSoundFile.test.cpp | 214 +++++------ test/Audio/Music.test.cpp | 155 ++++---- test/Audio/OutputSoundFile.test.cpp | 1 + test/Audio/Sound.test.cpp | 6 +- test/Audio/SoundBuffer.test.cpp | 123 +++--- test/Audio/SoundFileFactory.test.cpp | 14 +- test/Graphics/Drawable.test.cpp | 2 +- test/Graphics/Font.test.cpp | 199 +++++----- test/Graphics/Image.test.cpp | 232 +++++------ test/Graphics/Render.test.cpp | 4 +- test/Graphics/RenderTexture.test.cpp | 53 ++- test/Graphics/RenderWindow.test.cpp | 2 +- test/Graphics/Shader.test.cpp | 304 +++++++++------ test/Graphics/Shape.test.cpp | 4 +- test/Graphics/Sprite.test.cpp | 4 +- test/Graphics/Text.test.cpp | 6 +- test/Graphics/Texture.test.cpp | 229 +++++------ test/System/FileInputStream.test.cpp | 44 ++- test/System/MemoryInputStream.test.cpp | 11 +- test/Window/Cursor.test.cpp | 31 ++ .../SFML/SFML App.xctemplate/main.cpp | 10 +- .../SFML/SFML CLT.xctemplate/main.cpp | 10 +- 67 files changed, 1994 insertions(+), 1897 deletions(-) diff --git a/doc/mainpage.hpp b/doc/mainpage.hpp index 561deb458d..2750e097ca 100644 --- a/doc/mainpage.hpp +++ b/doc/mainpage.hpp @@ -21,15 +21,15 @@ /// sf::RenderWindow window(sf::VideoMode({800, 600}), "SFML window"); /// /// // 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); /// /// // 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); /// /// // Load a music to play -/// auto music = sf::Music::openFromFile("nice_music.ogg").value(); +/// sf::Music music("nice_music.ogg"); /// /// // Play the music /// music.play(); diff --git a/examples/android/app/src/main/jni/main.cpp b/examples/android/app/src/main/jni/main.cpp index abc025e292..0078e5820e 100644 --- a/examples/android/app/src/main/jni/main.cpp +++ b/examples/android/app/src/main/jni/main.cpp @@ -86,13 +86,13 @@ int main(int argc, char* argv[]) sf::RenderWindow window(screen, ""); window.setFramerateLimit(30); - const auto texture = sf::Texture::createFromFile("image.png").value(); + const sf::Texture texture("image.png"); sf::Sprite image(texture); image.setPosition(sf::Vector2f(screen.size) / 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); text.setFillColor(sf::Color::Black); diff --git a/examples/cocoa/CocoaAppDelegate.mm b/examples/cocoa/CocoaAppDelegate.mm index 327f3a9166..ae4def03b6 100644 --- a/examples/cocoa/CocoaAppDelegate.mm +++ b/examples/cocoa/CocoaAppDelegate.mm @@ -52,9 +52,9 @@ std::filesystem::path resPath{[[[NSBundle mainBundle] resourcePath] tostdstring]}; sf::RenderWindow renderWindow; - sf::Font font{sf::Font::createFromFile(resPath / "tuffy.ttf").value()}; + sf::Font font{resPath / "tuffy.ttf"}; 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::Color background{sf::Color::Blue}; }; diff --git a/examples/event_handling/EventHandling.cpp b/examples/event_handling/EventHandling.cpp index 263a7b3829..b14d413e23 100644 --- a/examples/event_handling/EventHandling.cpp +++ b/examples/event_handling/EventHandling.cpp @@ -316,7 +316,7 @@ class Application // Member data //////////////////////////////////////////////////////////// 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_handlerText{m_font, "Current Handler: Classic", 24}; sf::Text m_instructions{m_font, "Press Enter to change handler type", 24}; diff --git a/examples/island/Island.cpp b/examples/island/Island.cpp index fb02ec8fe0..8a356a5f64 100644 --- a/examples/island/Island.cpp +++ b/examples/island/Island.cpp @@ -91,14 +91,14 @@ int main() sf::RenderWindow window(sf::VideoMode({windowWidth, windowHeight}), "SFML Island", sf::Style::Titlebar | sf::Style::Close); 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 - sf::Text hudText(font); - sf::Text statusText(font); - std::optional terrainShader; - sf::RenderStates terrainStates; - sf::VertexBuffer terrain(sf::PrimitiveType::Triangles, sf::VertexBuffer::Usage::Static); + sf::Text hudText(font); + sf::Text statusText(font); + sf::Shader terrainShader; + sf::RenderStates terrainStates; + sf::VertexBuffer terrain(sf::PrimitiveType::Triangles, sf::VertexBuffer::Usage::Static); // Set up our text drawables statusText.setCharacterSize(28); @@ -120,7 +120,7 @@ int main() { 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"); } @@ -148,7 +148,7 @@ int main() statusText.setString("Generating Terrain..."); // Set up the render states - terrainStates = sf::RenderStates(&*terrainShader); + terrainStates = sf::RenderStates(&terrainShader); } // Center the status text @@ -186,7 +186,8 @@ int main() } // Arrow key pressed: - if (terrainShader.has_value() && event->is()) + // TODO Replace use of getNativeHandle() when validity function is added + if (terrainShader.getNativeHandle() != 0 && event->is()) { switch (event->getIf()->code) { @@ -216,7 +217,7 @@ int main() window.draw(statusText); - if (terrainShader.has_value()) + if (terrainShader.getNativeHandle() != 0) { { const std::lock_guard lock(workQueueMutex); @@ -236,7 +237,7 @@ int main() bufferUploadPending = false; } - terrainShader->setUniform("lightFactor", lightFactor); + terrainShader.setUniform("lightFactor", lightFactor); window.draw(terrain, terrainStates); } } diff --git a/examples/joystick/Joystick.cpp b/examples/joystick/Joystick.cpp index 011ef33cb9..abd1fea76b 100644 --- a/examples/joystick/Joystick.cpp +++ b/examples/joystick/Joystick.cpp @@ -94,7 +94,7 @@ int main() window.setVerticalSyncEnabled(true); // 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 sstr.precision(2); diff --git a/examples/opengl/OpenGL.cpp b/examples/opengl/OpenGL.cpp index ed369639d0..6d7f773322 100644 --- a/examples/opengl/OpenGL.cpp +++ b/examples/opengl/OpenGL.cpp @@ -58,11 +58,11 @@ int main() window.setMaximumSize(sf::Vector2u(1200, 900)); // Create a sprite for the background - const auto backgroundTexture = sf::Texture::createFromFile(resourcesDir() / "background.jpg", sRgb).value(); - const sf::Sprite background(backgroundTexture); + const sf::Texture backgroundTexture(resourcesDir() / "background.jpg", sRgb); + const sf::Sprite background(backgroundTexture); // 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 sRgbInstructions(font, "Press space to toggle sRGB conversion"); @@ -75,7 +75,7 @@ int main() mipmapInstructions.setPosition({200.f, 550.f}); // 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 // We don't check the return value here since @@ -219,7 +219,7 @@ int main() if (mipmapEnabled) { // 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 sf::Texture::bind(&texture); diff --git a/examples/raw_input/RawInput.cpp b/examples/raw_input/RawInput.cpp index 2faeb9be5d..8a7c6f2cb1 100644 --- a/examples/raw_input/RawInput.cpp +++ b/examples/raw_input/RawInput.cpp @@ -19,7 +19,7 @@ int main() window.setVerticalSyncEnabled(true); // 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 sf::Text mousePosition(font, "", 20); diff --git a/examples/shader/Shader.cpp b/examples/shader/Shader.cpp index 5e4543c091..cedb20b26b 100644 --- a/examples/shader/Shader.cpp +++ b/examples/shader/Shader.cpp @@ -278,69 +278,66 @@ class Geometry : public Effect //////////////////////////////////////////////////////////// std::optional tryLoadPixelate() { - auto texture = sf::Texture::createFromFile("resources/background.jpg"); - if (!texture.has_value()) + sf::Texture texture; + if (!texture.loadFromFile("resources/background.jpg")) return std::nullopt; - auto shader = sf::Shader::createFromFile("resources/pixelate.frag", sf::Shader::Type::Fragment); - if (!shader.has_value()) + sf::Shader shader; + if (!shader.loadFromFile("resources/pixelate.frag", sf::Shader::Type::Fragment)) return std::nullopt; - return std::make_optional(std::move(*texture), std::move(*shader)); + return std::make_optional(std::move(texture), std::move(shader)); } std::optional tryLoadWaveBlur(const sf::Font& font) { - auto shader = sf::Shader::createFromFile("resources/wave.vert", "resources/blur.frag"); - if (!shader.has_value()) + sf::Shader shader; + if (!shader.loadFromFile("resources/wave.vert", "resources/blur.frag")) return std::nullopt; - return std::make_optional(font, std::move(*shader)); + return std::make_optional(font, std::move(shader)); } std::optional tryLoadStormBlink() { - auto shader = sf::Shader::createFromFile("resources/storm.vert", "resources/blink.frag"); - if (!shader.has_value()) + sf::Shader shader; + if (!shader.loadFromFile("resources/storm.vert", "resources/blink.frag")) return std::nullopt; - return std::make_optional(std::move(*shader)); + return std::make_optional(std::move(shader)); } std::optional tryLoadEdge() { // Create the off-screen surface - auto surface = sf::RenderTexture::create({800, 600}); - if (!surface.has_value()) + sf::RenderTexture surface; + if (!surface.resize({800, 600})) return std::nullopt; - surface->setSmooth(true); + surface.setSmooth(true); // Load the background texture - auto backgroundTexture = sf::Texture::createFromFile("resources/sfml.png"); - if (!backgroundTexture.has_value()) + sf::Texture backgroundTexture; + if (!backgroundTexture.loadFromFile("resources/sfml.png")) return std::nullopt; - backgroundTexture->setSmooth(true); + backgroundTexture.setSmooth(true); // Load the entity texture - auto entityTexture = sf::Texture::createFromFile("resources/devices.png"); - if (!entityTexture.has_value()) + sf::Texture entityTexture; + if (!entityTexture.loadFromFile("resources/devices.png")) return std::nullopt; - entityTexture->setSmooth(true); + entityTexture.setSmooth(true); // Load the shader - auto shader = sf::Shader::createFromFile("resources/edge.frag", sf::Shader::Type::Fragment); - if (!shader.has_value()) + sf::Shader shader; + if (!shader.loadFromFile("resources/edge.frag", sf::Shader::Type::Fragment)) return std::nullopt; - shader->setUniform("texture", sf::Shader::CurrentTexture); + shader.setUniform("texture", sf::Shader::CurrentTexture); - return std::make_optional(std::move(*surface), - std::move(*backgroundTexture), - std::move(*entityTexture), - std::move(*shader)); + return std::make_optional(std::move(surface), std::move(backgroundTexture), std::move(entityTexture), std::move(shader)); } std::optional tryLoadGeometry() @@ -350,25 +347,23 @@ std::optional tryLoadGeometry() return std::nullopt; // Load the logo texture - auto logoTexture = sf::Texture::createFromFile("resources/logo.png"); - if (!logoTexture.has_value()) + sf::Texture logoTexture; + if (!logoTexture.loadFromFile("resources/logo.png")) return std::nullopt; - logoTexture->setSmooth(true); + logoTexture.setSmooth(true); // Load the shader - auto shader = sf::Shader::createFromFile("resources/billboard.vert", - "resources/billboard.geom", - "resources/billboard.frag"); - if (!shader.has_value()) + sf::Shader shader; + if (!shader.loadFromFile("resources/billboard.vert", "resources/billboard.geom", "resources/billboard.frag")) return std::nullopt; - shader->setUniform("texture", sf::Shader::CurrentTexture); + shader.setUniform("texture", sf::Shader::CurrentTexture); // 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(std::move(*logoTexture), std::move(*shader)); + return std::make_optional(std::move(logoTexture), std::move(shader)); } } // namespace @@ -394,7 +389,7 @@ int main() window.setVerticalSyncEnabled(true); // Open the application font - const auto font = sf::Font::createFromFile("resources/tuffy.ttf").value(); + const sf::Font font("resources/tuffy.ttf"); // Create the effects std::optional pixelateEffect = tryLoadPixelate(); @@ -418,8 +413,8 @@ int main() std::size_t current = 0; // Create the messages background - const auto textBackgroundTexture = sf::Texture::createFromFile("resources/text-background.png").value(); - sf::Sprite textBackground(textBackgroundTexture); + const sf::Texture textBackgroundTexture("resources/text-background.png"); + sf::Sprite textBackground(textBackgroundTexture); textBackground.setPosition({0.f, 520.f}); textBackground.setColor(sf::Color(255, 255, 255, 200)); diff --git a/examples/sound/Sound.cpp b/examples/sound/Sound.cpp index 99f95ccc2d..fe17d31140 100644 --- a/examples/sound/Sound.cpp +++ b/examples/sound/Sound.cpp @@ -13,7 +13,7 @@ void playSound() { // 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 std::cout << "killdeer.wav:" << '\n' @@ -46,7 +46,7 @@ void playSound() void playMusic(const std::filesystem::path& filename) { // Load an ogg music file - auto music = sf::Music::createFromFile("resources" / filename).value(); + sf::Music music("resources" / filename); // Display music information std::cout << filename << ":" << '\n' diff --git a/examples/sound_effects/SoundEffects.cpp b/examples/sound_effects/SoundEffects.cpp index b98e0ffcbb..90787aa374 100644 --- a/examples/sound_effects/SoundEffects.cpp +++ b/examples/sound_effects/SoundEffects.cpp @@ -115,23 +115,23 @@ class Surround : public Effect m_listener.setFillColor(sf::Color::Red); // 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::abort(); } // Set the music to loop - m_music->setLoop(true); + m_music.setLoop(true); // 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 { 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 @@ -149,19 +149,19 @@ class Surround : public Effect // Synchronize listener audio position with graphical position sf::Listener::setPosition({m_listener.getPosition().x, m_listener.getPosition().y, 0.f}); - m_music->play(); + m_music.play(); } void onStop() override { - m_music->stop(); + m_music.stop(); } private: - sf::CircleShape m_listener{20.f}; - sf::CircleShape m_soundShape{20.f}; - sf::Vector2f m_position; - std::optional m_music; + sf::CircleShape m_listener{20.f}; + sf::CircleShape m_soundShape{20.f}; + sf::Vector2f m_position; + sf::Music m_music; }; @@ -177,23 +177,23 @@ class PitchVolume : public Effect m_volumeText(getFont(), "Volume: " + std::to_string(m_volume)) { // 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::abort(); } // Set the music to loop - m_music->setLoop(true); + m_music.setLoop(true); // We don't care about attenuation in this effect - m_music->setAttenuation(0.f); + m_music.setAttenuation(0.f); // Set initial pitch - m_music->setPitch(m_pitch); + m_music.setPitch(m_pitch); // 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_volumeText.setPosition({windowWidth / 2.f - 120.f, windowHeight / 2.f - 30.f}); @@ -204,8 +204,8 @@ class PitchVolume : public Effect 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_music->setPitch(m_pitch); - m_music->setVolume(m_volume); + m_music.setPitch(m_pitch); + m_music.setVolume(m_volume); m_pitchText.setString("Pitch: " + std::to_string(m_pitch)); m_volumeText.setString("Volume: " + std::to_string(m_volume)); @@ -223,20 +223,20 @@ class PitchVolume : public Effect // so that the music is right on top of the listener sf::Listener::setPosition({0.f, 0.f, 0.f}); - m_music->play(); + m_music.play(); } void onStop() override { - m_music->stop(); + m_music.stop(); } private: - float m_pitch{1.f}; - float m_volume{100.f}; - sf::Text m_pitchText; - sf::Text m_volumeText; - std::optional m_music; + float m_pitch{1.f}; + float m_volume{100.f}; + sf::Text m_pitchText; + sf::Text m_volumeText; + sf::Music m_music; }; @@ -283,23 +283,23 @@ class Attenuation : public Effect makeCone(m_soundConeInner, innerConeAngle); // 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::abort(); } // Set the music to loop - m_music->setLoop(true); + m_music.setLoop(true); // Set attenuation factor - m_music->setAttenuation(m_attenuation); + m_music.setAttenuation(m_attenuation); // 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 - m_music->setCone({innerConeAngle, outerConeAngle, 0.f}); + m_music.setCone({innerConeAngle, outerConeAngle, 0.f}); m_text.setString( "Attenuation factor dampens full volume of sound while within inner cone based on distance to " @@ -314,7 +314,7 @@ class Attenuation : public Effect void onUpdate(float /*time*/, float x, float y) override { 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 @@ -336,22 +336,22 @@ class Attenuation : public Effect // Synchronize listener audio position with graphical position sf::Listener::setPosition({m_listener.getPosition().x, m_listener.getPosition().y, 0.f}); - m_music->play(); + m_music.play(); } void onStop() override { - m_music->stop(); + m_music.stop(); } private: - sf::CircleShape m_listener{20.f}; - sf::CircleShape m_soundShape{20.f}; - sf::ConvexShape m_soundConeOuter; - sf::ConvexShape m_soundConeInner; - sf::Text m_text; - sf::Vector2f m_position; - std::optional m_music; + sf::CircleShape m_listener{20.f}; + sf::CircleShape m_soundShape{20.f}; + sf::ConvexShape m_soundConeOuter; + sf::ConvexShape m_soundConeInner; + sf::Text m_text; + sf::Vector2f m_position; + sf::Music m_music; float m_attenuation{0.01f}; }; @@ -636,7 +636,7 @@ class Processing : public Effect void onUpdate([[maybe_unused]] float time, float x, float y) override { 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 @@ -656,12 +656,12 @@ class Processing : public Effect // Synchronize listener audio position with graphical position sf::Listener::setPosition({m_listener.getPosition().x, m_listener.getPosition().y, 0.f}); - m_music->play(); + m_music.play(); } void onStop() override { - m_music->stop(); + m_music.stop(); } protected: @@ -677,22 +677,22 @@ class Processing : public Effect m_instructions.setPosition({windowWidth / 2.f - 250.f, windowHeight * 3.f / 4.f}); // 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::abort(); } // Set the music to loop - m_music->setLoop(true); + m_music.setLoop(true); // Set attenuation to a nice value - m_music->setAttenuation(0.0f); + m_music.setAttenuation(0.0f); } sf::Music& getMusic() { - return *m_music; + return m_music; } const std::shared_ptr& getEnabled() const @@ -709,13 +709,13 @@ class Processing : public Effect m_enabledText.setString(*m_enabled ? "Processing: Enabled" : "Processing: Disabled"); } - sf::CircleShape m_listener{20.f}; - sf::CircleShape m_soundShape{20.f}; - sf::Vector2f m_position; - std::optional m_music; - std::shared_ptr m_enabled{std::make_shared(true)}; - sf::Text m_enabledText; - sf::Text m_instructions; + sf::CircleShape m_listener{20.f}; + sf::CircleShape m_soundShape{20.f}; + sf::Vector2f m_position; + sf::Music m_music; + std::shared_ptr m_enabled{std::make_shared(true)}; + sf::Text m_enabledText; + sf::Text m_instructions; }; @@ -1077,7 +1077,7 @@ int main() window.setVerticalSyncEnabled(true); // 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); // Create the effects @@ -1106,8 +1106,8 @@ int main() effects[current]->start(); // Create the messages background - const auto textBackgroundTexture = sf::Texture::createFromFile(resourcesDir() / "text-background.png").value(); - sf::Sprite textBackground(textBackgroundTexture); + const sf::Texture textBackgroundTexture(resourcesDir() / "text-background.png"); + sf::Sprite textBackground(textBackgroundTexture); textBackground.setPosition({0.f, 520.f}); textBackground.setColor(sf::Color(255, 255, 255, 200)); diff --git a/examples/tennis/Tennis.cpp b/examples/tennis/Tennis.cpp index 4d5b0ab08d..0aa62a67c8 100644 --- a/examples/tennis/Tennis.cpp +++ b/examples/tennis/Tennis.cpp @@ -49,12 +49,12 @@ int main() window.setVerticalSyncEnabled(true); // Load the sounds used in the game - const auto ballSoundBuffer = sf::SoundBuffer::createFromFile(resourcesDir() / "ball.wav").value(); - sf::Sound ballSound(ballSoundBuffer); + const sf::SoundBuffer ballSoundBuffer(resourcesDir() / "ball.wav"); + sf::Sound ballSound(ballSoundBuffer); // Create the SFML logo texture: - const auto sfmlLogoTexture = sf::Texture::createFromFile(resourcesDir() / "sfml_logo.png").value(); - sf::Sprite sfmlLogo(sfmlLogoTexture); + const sf::Texture sfmlLogoTexture(resourcesDir() / "sfml_logo.png"); + sf::Sprite sfmlLogo(sfmlLogoTexture); sfmlLogo.setPosition({170.f, 50.f}); // Create the left paddle @@ -82,7 +82,7 @@ int main() ball.setOrigin({ballRadius / 2.f, ballRadius / 2.f}); // 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 sf::Text pauseMessage(font); diff --git a/examples/vulkan/Vulkan.cpp b/examples/vulkan/Vulkan.cpp index 315b6f8fd3..4157eb9d9a 100644 --- a/examples/vulkan/Vulkan.cpp +++ b/examples/vulkan/Vulkan.cpp @@ -923,17 +923,17 @@ class VulkanExample // Use the vertex shader SPIR-V code to create a vertex shader module { - auto file = sf::FileInputStream::create("resources/shader.vert.spv"); - if (!file) + sf::FileInputStream file; + if (!file.open("resources/shader.vert.spv")) { vulkanAvailable = false; return; } - const auto fileSize = file->getSize().value(); + const auto fileSize = file.getSize().value(); std::vector buffer(fileSize / sizeof(std::uint32_t)); - if (file->read(buffer.data(), fileSize) != file->getSize()) + if (file.read(buffer.data(), fileSize) != file.getSize()) { vulkanAvailable = false; return; @@ -951,17 +951,17 @@ class VulkanExample // Use the fragment shader SPIR-V code to create a fragment shader module { - auto file = sf::FileInputStream::create("resources/shader.frag.spv"); - if (!file) + sf::FileInputStream file; + if (!file.open("resources/shader.frag.spv")) { vulkanAvailable = false; return; } - const auto fileSize = file->getSize().value(); + const auto fileSize = file.getSize().value(); std::vector buffer(fileSize / sizeof(std::uint32_t)); - if (file->read(buffer.data(), fileSize) != file->getSize()) + if (file.read(buffer.data(), fileSize) != file.getSize()) { vulkanAvailable = false; return; @@ -1801,16 +1801,13 @@ class VulkanExample void setupTextureImage() { // Load the image data - const auto maybeImageData = sf::Image::createFromFile("resources/logo.png"); - - if (!maybeImageData) + sf::Image imageData; + if (!imageData.loadFromFile("resources/logo.png")) { vulkanAvailable = false; return; } - const auto& imageData = *maybeImageData; - // Create a staging buffer to transfer the data with const VkDeviceSize imageSize = imageData.getSize().x * imageData.getSize().y * 4; diff --git a/examples/win32/Win32.cpp b/examples/win32/Win32.cpp index c5679cf05f..b5c9f9e636 100644 --- a/examples/win32/Win32.cpp +++ b/examples/win32/Win32.cpp @@ -111,10 +111,10 @@ int main() sf::RenderWindow sfmlView2(view2); // Load some textures to display - const auto texture1 = sf::Texture::createFromFile("resources/image1.jpg").value(); - const auto texture2 = sf::Texture::createFromFile("resources/image2.jpg").value(); - sf::Sprite sprite1(texture1); - sf::Sprite sprite2(texture2); + const sf::Texture texture1("resources/image1.jpg"); + const sf::Texture texture2("resources/image2.jpg"); + sf::Sprite sprite1(texture1); + sf::Sprite sprite2(texture2); sprite1.setOrigin(sf::Vector2f(texture1.getSize()) / 2.f); sprite1.setPosition(sprite1.getOrigin()); diff --git a/include/SFML/Audio/InputSoundFile.hpp b/include/SFML/Audio/InputSoundFile.hpp index 07ff47b171..1544339c67 100644 --- a/include/SFML/Audio/InputSoundFile.hpp +++ b/include/SFML/Audio/InputSoundFile.hpp @@ -33,7 +33,6 @@ #include #include -#include #include #include @@ -62,7 +61,7 @@ class SFML_AUDIO_API InputSoundFile InputSoundFile() = default; //////////////////////////////////////////////////////////// - /// \brief Open a sound file from the disk for reading + /// \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. @@ -74,13 +73,13 @@ class SFML_AUDIO_API InputSoundFile /// /// \param filename Path of the sound file to load /// - /// \return True if the file was successfully opened + /// \throws std::runtime_error if opening the file was unsuccessful /// //////////////////////////////////////////////////////////// - [[nodiscard]] bool openFromFile(const std::filesystem::path& filename); + InputSoundFile(const std::filesystem::path& filename); //////////////////////////////////////////////////////////// - /// \brief Open a sound file in memory for reading + /// \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. @@ -88,26 +87,26 @@ class SFML_AUDIO_API InputSoundFile /// \param data Pointer to the file data in memory /// \param sizeInBytes Size of the data to load, in bytes /// - /// \return True if the file was successfully opened + /// \throws std::runtime_error if opening the file was unsuccessful /// //////////////////////////////////////////////////////////// - [[nodiscard]] bool openFromMemory(const void* data, std::size_t sizeInBytes); + InputSoundFile(const void* data, std::size_t sizeInBytes); //////////////////////////////////////////////////////////// - /// \brief Open a sound file from a custom stream for reading + /// \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 /// - /// \return True if the file was successfully opened + /// \throws std::runtime_error if opening the file was unsuccessful /// //////////////////////////////////////////////////////////// - [[nodiscard]] bool openFromStream(InputStream& stream); + InputSoundFile(InputStream& stream); //////////////////////////////////////////////////////////// - /// \brief Create a sound file from the disk for reading + /// \brief Open 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. @@ -119,13 +118,13 @@ class SFML_AUDIO_API InputSoundFile /// /// \param filename Path of the sound file to load /// - /// \return Input sound file if the file was successfully opened, otherwise `std::nullopt` + /// \return True if the file was successfully opened /// //////////////////////////////////////////////////////////// - [[nodiscard]] static std::optional createFromFile(const std::filesystem::path& filename); + [[nodiscard]] bool openFromFile(const std::filesystem::path& filename); //////////////////////////////////////////////////////////// - /// \brief Create a sound file in memory for reading + /// \brief Open 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. @@ -133,23 +132,23 @@ class SFML_AUDIO_API InputSoundFile /// \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` + /// \return True if the file was successfully opened /// //////////////////////////////////////////////////////////// - [[nodiscard]] static std::optional createFromMemory(const void* data, std::size_t sizeInBytes); + [[nodiscard]] bool openFromMemory(const void* data, std::size_t sizeInBytes); //////////////////////////////////////////////////////////// - /// \brief Create a sound file from a custom stream for reading + /// \brief Open 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` + /// \return True if the file was successfully opened /// //////////////////////////////////////////////////////////// - [[nodiscard]] static std::optional createFromStream(InputStream& stream); + [[nodiscard]] bool openFromStream(InputStream& stream); //////////////////////////////////////////////////////////// /// \brief Get the total number of audio samples in the file @@ -311,7 +310,7 @@ class SFML_AUDIO_API InputSoundFile /// Usage example: /// \code /// // Open a sound file -/// auto file = sf::InputSoundFile::createFromFile("music.ogg").value(); +/// sf::InputSoundFile file("music.ogg"); /// /// // Print the sound attributes /// std::cout << "duration: " << file.getDuration().asSeconds() << '\n' diff --git a/include/SFML/Audio/Music.hpp b/include/SFML/Audio/Music.hpp index 546fe220bb..54e6b6c104 100644 --- a/include/SFML/Audio/Music.hpp +++ b/include/SFML/Audio/Music.hpp @@ -75,25 +75,7 @@ class SFML_AUDIO_API Music : public SoundStream Music(); //////////////////////////////////////////////////////////// - /// \brief Destructor - /// - //////////////////////////////////////////////////////////// - ~Music() override; - - //////////////////////////////////////////////////////////// - /// \brief Move constructor - /// - //////////////////////////////////////////////////////////// - Music(Music&&) noexcept; - - //////////////////////////////////////////////////////////// - /// \brief Move assignment - /// - //////////////////////////////////////////////////////////// - Music& operator=(Music&&) noexcept; - - //////////////////////////////////////////////////////////// - /// \brief Open a music from an audio file + /// \brief Construct a music from an audio file /// /// This function doesn't start playing the music (call play() /// to do so). @@ -106,15 +88,15 @@ class SFML_AUDIO_API Music : public SoundStream /// /// \param filename Path of the music file to open /// - /// \return True if loading succeeded, false if it failed + /// \throws std::runtime_error if loading was unsuccessful /// /// \see openFromMemory, openFromStream /// //////////////////////////////////////////////////////////// - [[nodiscard]] bool openFromFile(const std::filesystem::path& filename); + Music(const std::filesystem::path& filename); //////////////////////////////////////////////////////////// - /// \brief Open a music from an audio file in memory + /// \brief Construct a music from an audio file in memory /// /// This function doesn't start playing the music (call play() /// to do so). @@ -129,15 +111,15 @@ class SFML_AUDIO_API Music : public SoundStream /// \param data Pointer to the file data in memory /// \param sizeInBytes Size of the data to load, in bytes /// - /// \return True if loading succeeded, false if it failed + /// \throws std::runtime_error if loading was unsuccessful /// /// \see openFromFile, openFromStream /// //////////////////////////////////////////////////////////// - [[nodiscard]] bool openFromMemory(const void* data, std::size_t sizeInBytes); + Music(const void* data, std::size_t sizeInBytes); //////////////////////////////////////////////////////////// - /// \brief Open a music from an audio file in a custom stream + /// \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). @@ -150,15 +132,33 @@ class SFML_AUDIO_API Music : public SoundStream /// /// \param stream Source stream to read from /// - /// \return True if loading succeeded, false if it failed + /// \throws std::runtime_error if loading was unsuccessful /// /// \see openFromFile, openFromMemory /// //////////////////////////////////////////////////////////// - [[nodiscard]] bool openFromStream(InputStream& stream); + Music(InputStream& stream); //////////////////////////////////////////////////////////// - /// \brief Create a music from an audio file + /// \brief Destructor + /// + //////////////////////////////////////////////////////////// + ~Music() override; + + //////////////////////////////////////////////////////////// + /// \brief Move constructor + /// + //////////////////////////////////////////////////////////// + Music(Music&&) noexcept; + + //////////////////////////////////////////////////////////// + /// \brief Move assignment + /// + //////////////////////////////////////////////////////////// + Music& operator=(Music&&) noexcept; + + //////////////////////////////////////////////////////////// + /// \brief Open a music from an audio file /// /// This function doesn't start playing the music (call play() /// to do so). @@ -171,15 +171,15 @@ class SFML_AUDIO_API Music : public SoundStream /// /// \param filename Path of the music file to open /// - /// \return Music if loading succeeded, `std::nullopt` if it failed + /// \return True if loading succeeded, false if it failed /// - /// \see createFromMemory, createFromStream + /// \see openFromMemory, openFromStream /// //////////////////////////////////////////////////////////// - [[nodiscard]] static std::optional createFromFile(const std::filesystem::path& filename); + [[nodiscard]] bool openFromFile(const std::filesystem::path& filename); //////////////////////////////////////////////////////////// - /// \brief Create a music from an audio file in memory + /// \brief Open a music from an audio file in memory /// /// This function doesn't start playing the music (call play() /// to do so). @@ -194,15 +194,15 @@ class SFML_AUDIO_API Music : public SoundStream /// \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 + /// \return True if loading succeeded, false if it failed /// - /// \see createFromFile, createFromStream + /// \see openFromFile, openFromStream /// //////////////////////////////////////////////////////////// - [[nodiscard]] static std::optional createFromMemory(const void* data, std::size_t sizeInBytes); + [[nodiscard]] bool openFromMemory(const void* data, std::size_t sizeInBytes); //////////////////////////////////////////////////////////// - /// \brief Create a music from an audio file in a custom stream + /// \brief Open a music from an audio file in a custom stream /// /// This function doesn't start playing the music (call play() /// to do so). @@ -215,12 +215,12 @@ class SFML_AUDIO_API Music : public SoundStream /// /// \param stream Source stream to read from /// - /// \return Music if loading succeeded, `std::nullopt` if it failed + /// \return True if loading succeeded, false if it failed /// - /// \see createFromFile, createFromMemory + /// \see openFromFile, openFromMemory /// //////////////////////////////////////////////////////////// - [[nodiscard]] static std::optional createFromStream(InputStream& stream); + [[nodiscard]] bool openFromStream(InputStream& stream); //////////////////////////////////////////////////////////// /// \brief Get the total duration of the music @@ -360,7 +360,7 @@ class SFML_AUDIO_API Music : public SoundStream /// Usage example: /// \code /// // Open a music from an audio file -/// auto music = sf::Music::createFromFile("music.ogg").value(); +/// sf::Music music("music.ogg"); /// /// // Change some parameters /// music.setPosition({0, 1, 10}); // change its 3D position diff --git a/include/SFML/Audio/OutputSoundFile.hpp b/include/SFML/Audio/OutputSoundFile.hpp index cbbc530bc3..7009179e88 100644 --- a/include/SFML/Audio/OutputSoundFile.hpp +++ b/include/SFML/Audio/OutputSoundFile.hpp @@ -34,7 +34,6 @@ #include #include -#include #include #include @@ -59,7 +58,7 @@ class SFML_AUDIO_API OutputSoundFile OutputSoundFile() = default; //////////////////////////////////////////////////////////// - /// \brief Open the sound file from the disk for writing + /// \brief Construct the sound file from the disk for writing /// /// The supported audio formats are: WAV, OGG/Vorbis, FLAC. /// @@ -68,16 +67,16 @@ class SFML_AUDIO_API OutputSoundFile /// \param channelCount Number of channels in the sound /// \param channelMap Map of position in sample frame to sound channel /// - /// \return True if the file was successfully opened + /// \throws std::runtime_error if the file could not be opened successfully /// //////////////////////////////////////////////////////////// - [[nodiscard]] bool openFromFile(const std::filesystem::path& filename, - unsigned int sampleRate, - unsigned int channelCount, - const std::vector& channelMap); + OutputSoundFile(const std::filesystem::path& filename, + unsigned int sampleRate, + unsigned int channelCount, + const std::vector& channelMap); //////////////////////////////////////////////////////////// - /// \brief Create the sound file from the disk for writing + /// \brief Open the sound file from the disk for writing /// /// The supported audio formats are: WAV, OGG/Vorbis, FLAC. /// @@ -86,14 +85,13 @@ class SFML_AUDIO_API OutputSoundFile /// \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 + /// \return True if the file was successfully opened /// //////////////////////////////////////////////////////////// - [[nodiscard]] static std::optional createFromFile( - const std::filesystem::path& filename, - unsigned int sampleRate, - unsigned int channelCount, - const std::vector& channelMap); + [[nodiscard]] bool openFromFile(const std::filesystem::path& filename, + unsigned int sampleRate, + unsigned int channelCount, + const std::vector& channelMap); //////////////////////////////////////////////////////////// /// \brief Write audio samples to the file @@ -132,7 +130,7 @@ class SFML_AUDIO_API OutputSoundFile /// Usage example: /// \code /// // 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 (...) /// { diff --git a/include/SFML/Audio/Sound.hpp b/include/SFML/Audio/Sound.hpp index 95f5dbeab3..2fd6e25b93 100644 --- a/include/SFML/Audio/Sound.hpp +++ b/include/SFML/Audio/Sound.hpp @@ -274,7 +274,7 @@ class SFML_AUDIO_API Sound : public SoundSource /// /// Usage example: /// \code -/// const auto buffer = sf::SoundBuffer::createFromFile("sound.wav").value(); +/// const sf::SoundBuffer buffer("sound.wav"); /// sf::Sound sound(buffer); /// sound.play(); /// \endcode diff --git a/include/SFML/Audio/SoundBuffer.hpp b/include/SFML/Audio/SoundBuffer.hpp index 1a0b088ce4..762fecdd89 100644 --- a/include/SFML/Audio/SoundBuffer.hpp +++ b/include/SFML/Audio/SoundBuffer.hpp @@ -34,7 +34,6 @@ #include #include -#include #include #include @@ -73,28 +72,22 @@ class SFML_AUDIO_API SoundBuffer SoundBuffer(const SoundBuffer& copy); //////////////////////////////////////////////////////////// - /// \brief Destructor - /// - //////////////////////////////////////////////////////////// - ~SoundBuffer(); - - //////////////////////////////////////////////////////////// - /// \brief Load the sound buffer from a file + /// \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 /// - /// \return True if loading succeeded, false if it failed + /// \throws std::runtime_error if loading was unsuccessful /// /// \see loadFromMemory, loadFromStream, loadFromSamples, saveToFile /// //////////////////////////////////////////////////////////// - [[nodiscard]] bool loadFromFile(const std::filesystem::path& filename); + SoundBuffer(const std::filesystem::path& filename); //////////////////////////////////////////////////////////// - /// \brief Load the sound buffer from a file in memory + /// \brief Construct the sound buffer from a file in memory /// /// See the documentation of sf::InputSoundFile for the list /// of supported formats. @@ -102,30 +95,30 @@ class SFML_AUDIO_API SoundBuffer /// \param data Pointer to the file data in memory /// \param sizeInBytes Size of the data to load, in bytes /// - /// \return True if loading succeeded, false if it failed + /// \throws std::runtime_error if loading was unsuccessful /// /// \see loadFromFile, loadFromStream, loadFromSamples /// //////////////////////////////////////////////////////////// - [[nodiscard]] bool loadFromMemory(const void* data, std::size_t sizeInBytes); + SoundBuffer(const void* data, std::size_t sizeInBytes); //////////////////////////////////////////////////////////// - /// \brief Load the sound buffer from a custom stream + /// \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 /// - /// \return True if loading succeeded, false if it failed + /// \throws std::runtime_error if loading was unsuccessful /// /// \see loadFromFile, loadFromMemory, loadFromSamples /// //////////////////////////////////////////////////////////// - [[nodiscard]] bool loadFromStream(InputStream& stream); + SoundBuffer(InputStream& stream); //////////////////////////////////////////////////////////// - /// \brief Load the sound buffer from an array of audio samples + /// \brief Construct the sound buffer from an array of audio samples /// /// The assumed format of the audio samples is 16 bit signed integer. /// @@ -135,34 +128,40 @@ class SFML_AUDIO_API SoundBuffer /// \param sampleRate Sample rate (number of samples to play per second) /// \param channelMap Map of position in sample frame to sound channel /// - /// \return True if loading succeeded, false if it failed + /// \throws std::runtime_error if loading was unsuccessful /// /// \see loadFromFile, loadFromMemory, saveToFile /// //////////////////////////////////////////////////////////// - [[nodiscard]] bool loadFromSamples(const std::int16_t* samples, - std::uint64_t sampleCount, - unsigned int channelCount, - unsigned int sampleRate, - const std::vector& channelMap); + SoundBuffer(const std::int16_t* samples, + std::uint64_t sampleCount, + unsigned int channelCount, + unsigned int sampleRate, + const std::vector& channelMap); + + //////////////////////////////////////////////////////////// + /// \brief Destructor + /// + //////////////////////////////////////////////////////////// + ~SoundBuffer(); //////////////////////////////////////////////////////////// - /// \brief Create the sound buffer from a file + /// \brief Load 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 + /// \return True if loading succeeded, false if it failed /// - /// \see createFromMemory, createFromStream, createFromSamples, saveToFile + /// \see loadFromMemory, loadFromStream, loadFromSamples, saveToFile /// //////////////////////////////////////////////////////////// - [[nodiscard]] static std::optional createFromFile(const std::filesystem::path& filename); + [[nodiscard]] bool loadFromFile(const std::filesystem::path& filename); //////////////////////////////////////////////////////////// - /// \brief Create the sound buffer from a file in memory + /// \brief Load the sound buffer from a file in memory /// /// See the documentation of sf::InputSoundFile for the list /// of supported formats. @@ -170,32 +169,32 @@ class SFML_AUDIO_API SoundBuffer /// \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 + /// \return True if loading succeeded, false if it failed /// - /// \see createFromFile, createFromStream, createFromSamples + /// \see loadFromFile, loadFromStream, loadFromSamples /// //////////////////////////////////////////////////////////// - [[nodiscard]] static std::optional createFromMemory(const void* data, std::size_t sizeInBytes); + [[nodiscard]] bool loadFromMemory(const void* data, std::size_t sizeInBytes); //////////////////////////////////////////////////////////// - /// \brief Create the sound buffer from a custom stream + /// \brief Load 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 + /// \return True if loading succeeded, false if it failed /// - /// \see createFromFile, createFromMemory, createFromSamples + /// \see loadFromFile, loadFromMemory, loadFromSamples /// //////////////////////////////////////////////////////////// - [[nodiscard]] static std::optional createFromStream(InputStream& stream); + [[nodiscard]] bool loadFromStream(InputStream& stream); //////////////////////////////////////////////////////////// - /// \brief Create the sound buffer from an array of audio samples + /// \brief Load the sound buffer from an array of audio samples /// - /// The assumed format of the audio samples is 16 bits signed integer. + /// 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 @@ -203,17 +202,16 @@ class SFML_AUDIO_API SoundBuffer /// \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 + /// \return True if loading succeeded, false if it failed /// - /// \see createFromFile, createFromMemory, saveToFile + /// \see loadFromFile, loadFromMemory, saveToFile /// //////////////////////////////////////////////////////////// - [[nodiscard]] static std::optional createFromSamples( - const std::int16_t* samples, - std::uint64_t sampleCount, - unsigned int channelCount, - unsigned int sampleRate, - const std::vector& channelMap); + [[nodiscard]] bool loadFromSamples(const std::int16_t* samples, + std::uint64_t sampleCount, + unsigned int channelCount, + unsigned int sampleRate, + const std::vector& channelMap); //////////////////////////////////////////////////////////// /// \brief Save the sound buffer to an audio file @@ -225,8 +223,6 @@ class SFML_AUDIO_API SoundBuffer /// /// \return True if saving succeeded, false if it failed /// - /// \see createFromFile, createFromMemory, createFromSamples - /// //////////////////////////////////////////////////////////// [[nodiscard]] bool saveToFile(const std::filesystem::path& filename) const; @@ -389,8 +385,7 @@ class SFML_AUDIO_API SoundBuffer /// are like texture pixels, and a sf::SoundBuffer is similar to /// a sf::Texture. /// -/// A sound buffer can be loaded from a file (see createFromFile() -/// for the complete list of supported formats), from memory, from +/// A sound buffer can be loaded from a file, from memory, from /// a custom stream (see sf::InputStream) or directly from an array /// of samples. It can also be saved back to a file. /// @@ -415,7 +410,7 @@ class SFML_AUDIO_API SoundBuffer /// Usage example: /// \code /// // 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 /// sf::Sound sound1(buffer); diff --git a/include/SFML/Graphics/Font.hpp b/include/SFML/Graphics/Font.hpp index a36bb73dd7..a2021749eb 100644 --- a/include/SFML/Graphics/Font.hpp +++ b/include/SFML/Graphics/Font.hpp @@ -37,7 +37,6 @@ #include #include -#include #include #include #include @@ -82,7 +81,7 @@ class SFML_GRAPHICS_API Font Font() = default; //////////////////////////////////////////////////////////// - /// \brief Open the font from a file + /// \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. @@ -92,40 +91,40 @@ class SFML_GRAPHICS_API Font /// /// \warning SFML cannot preload all the font data in this /// 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 open /// - /// \return True if loading succeeded, false if it failed + /// \throws std::runtime_error if opening was unsuccessful /// - /// \see openFromMemory, openFromStream + /// \see openFromFile, openFromMemory, openFromStream /// //////////////////////////////////////////////////////////// - [[nodiscard]] bool openFromFile(const std::filesystem::path& filename); + Font(const std::filesystem::path& filename); //////////////////////////////////////////////////////////// - /// \brief Open the font from a file in memory + /// \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 loads a new font or + /// 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 /// - /// \return True if loading succeeded, false if it failed + /// \throws std::runtime_error if loading was unsuccessful /// - /// \see openFromFile, openFromStream + /// \see openFromFile, openFromMemory, openFromStream /// //////////////////////////////////////////////////////////// - [[nodiscard]] bool openFromMemory(const void* data, std::size_t sizeInBytes); + Font(const void* data, std::size_t sizeInBytes); //////////////////////////////////////////////////////////// - /// \brief Open the font from a custom stream + /// \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. @@ -135,19 +134,19 @@ class SFML_GRAPHICS_API Font /// /// \warning SFML cannot preload all the font data in this /// 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 /// - /// \return True if loading succeeded, false if it failed + /// \throws std::runtime_error if loading was unsuccessful /// - /// \see openFromFile, openFromMemory + /// \see openFromFile, openFromMemory, openFromStream /// //////////////////////////////////////////////////////////// - [[nodiscard]] bool openFromStream(InputStream& stream); + Font(InputStream& stream); //////////////////////////////////////////////////////////// - /// \brief Create the font from a file + /// \brief Open 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. @@ -157,55 +156,56 @@ class SFML_GRAPHICS_API Font /// /// \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. + /// the sf::Font object opens a new font or is destroyed. /// /// \param filename Path of the font file to load /// - /// \return Font if opening succeeded, `std::nullopt` if it failed + /// \return True if opening succeeded, false if it failed /// - /// \see createFromMemory, createFromStream + /// \see openFromMemory, openFromStream /// //////////////////////////////////////////////////////////// - [[nodiscard]] static std::optional createFromFile(const std::filesystem::path& filename); + [[nodiscard]] bool openFromFile(const std::filesystem::path& filename); //////////////////////////////////////////////////////////// - /// \brief Create the font from a file in memory + /// \brief Open 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. + /// 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 /// - /// \return Font if opening succeeded, `std::nullopt` if it failed + /// \return True if opening succeeded, false if it failed /// - /// \see createFromFile, createFromStream + /// \see openFromFile, openFromStream /// //////////////////////////////////////////////////////////// - [[nodiscard]] static std::optional createFromMemory(const void* data, std::size_t sizeInBytes); + [[nodiscard]] bool openFromMemory(const void* data, std::size_t sizeInBytes); //////////////////////////////////////////////////////////// - /// \brief Create the font from a custom stream + /// \brief Open 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. + /// the sf::Font object opens a new font or is destroyed. /// /// \param stream Source stream to read from /// - /// \return Font if opening succeeded, `std::nullopt` if it failed + /// \return True if opening succeeded, false if it failed /// - /// \see createFromFile, createFromMemory + /// \see openFromFile, openFromMemory /// //////////////////////////////////////////////////////////// - [[nodiscard]] static std::optional createFromStream(InputStream& stream); + [[nodiscard]] bool openFromStream(InputStream& stream); //////////////////////////////////////////////////////////// /// \brief Get the font information @@ -474,7 +474,7 @@ class SFML_GRAPHICS_API Font /// /// Fonts can be opened from a file, from memory or from a custom /// 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 /// types of information about the font: @@ -505,7 +505,7 @@ class SFML_GRAPHICS_API Font /// Usage example: /// \code /// // 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 /// sf::Text text1(font); diff --git a/include/SFML/Graphics/Image.hpp b/include/SFML/Graphics/Image.hpp index 8e41310e15..46d3053d47 100644 --- a/include/SFML/Graphics/Image.hpp +++ b/include/SFML/Graphics/Image.hpp @@ -59,6 +59,8 @@ class SFML_GRAPHICS_API Image /// /// Constructs an image with width 0 and height 0. /// + /// \see resize + /// //////////////////////////////////////////////////////////// Image() = default; @@ -86,79 +88,76 @@ class SFML_GRAPHICS_API Image Image(Vector2u size, const std::uint8_t* pixels); //////////////////////////////////////////////////////////// - /// \brief Resize the image and fill it with a unique color + /// \brief Construct the image from a file on disk /// - /// \param size Width and height of the image - /// \param color Fill color + /// 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. /// - //////////////////////////////////////////////////////////// - void resize(Vector2u size, Color color = Color::Black); - - //////////////////////////////////////////////////////////// - /// \brief Resize the image from an array of pixels + /// \param filename Path of the image file to load /// - /// The \a pixel array is assumed to contain 32-bits RGBA pixels, - /// and have the given \a width and \a height. If not, this is - /// an undefined behavior. - /// If \a pixels is null, an empty image is created. + /// \throws std::runtime_error if loading was unsuccessful /// - /// \param size Width and height of the image - /// \param pixels Array of pixels to copy to the image + /// \see loadFromFile, loadFromMemory, loadFromStream /// //////////////////////////////////////////////////////////// - void resize(Vector2u size, const std::uint8_t* pixels); + explicit Image(const std::filesystem::path& filename); //////////////////////////////////////////////////////////// - /// \brief Load the image from a file on disk + /// \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. - /// If this function fails, the image is left unchanged. /// - /// \param filename Path of the image file to load + /// \param data Pointer to the file data in memory + /// \param size Size of the data to load, in bytes /// - /// \return True if loading was successful + /// \throws std::runtime_error if loading was unsuccessful /// - /// \see loadFromMemory, loadFromStream, saveToFile + /// \see loadFromFile, loadFromMemory, loadFromStream /// //////////////////////////////////////////////////////////// - [[nodiscard]] bool loadFromFile(const std::filesystem::path& filename); + Image(const void* data, std::size_t size); //////////////////////////////////////////////////////////// - /// \brief Load the image from a file in memory + /// \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. - /// 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 + /// \param stream Source stream to read from /// - /// \return True if loading was successful + /// \throws std::runtime_error if loading was unsuccessful /// - /// \see loadFromFile, loadFromStream + /// \see loadFromFile, loadFromMemory, loadFromStream /// //////////////////////////////////////////////////////////// - [[nodiscard]] bool loadFromMemory(const void* data, std::size_t size); + explicit Image(InputStream& stream); //////////////////////////////////////////////////////////// - /// \brief Load the image from a custom stream + /// \brief Resize the image and fill it with a unique color /// - /// 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 size Width and height of the image + /// \param color Fill color /// - /// \param stream Source stream to read from + //////////////////////////////////////////////////////////// + void resize(Vector2u size, Color color = Color::Black); + + //////////////////////////////////////////////////////////// + /// \brief Resize the image from an array of pixels /// - /// \return True if loading was successful + /// The \a pixel array is assumed to contain 32-bits RGBA pixels, + /// and have the given \a width and \a height. If not, this is + /// an undefined behavior. + /// If \a pixels is null, an empty image is created. /// - /// \see loadFromFile, loadFromMemory + /// \param size Width and height of the image + /// \param pixels Array of pixels to copy to the image /// //////////////////////////////////////////////////////////// - [[nodiscard]] bool loadFromStream(InputStream& stream); + void resize(Vector2u size, const std::uint8_t* pixels); //////////////////////////////////////////////////////////// /// \brief Load the image from a file on disk @@ -170,12 +169,12 @@ class SFML_GRAPHICS_API Image /// /// \param filename Path of the image file to load /// - /// \return Image if loading was successful, `std::nullopt` otherwise + /// \return True if loading was successful /// - /// \see createFromMemory, createFromStream, saveToFile + /// \see loadFromMemory, loadFromStream, saveToFile /// //////////////////////////////////////////////////////////// - [[nodiscard]] static std::optional createFromFile(const std::filesystem::path& filename); + [[nodiscard]] bool loadFromFile(const std::filesystem::path& filename); //////////////////////////////////////////////////////////// /// \brief Load the image from a file in memory @@ -188,12 +187,12 @@ class SFML_GRAPHICS_API Image /// \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 + /// \return True if loading was successful /// - /// \see createFromFile, createFromStream + /// \see loadFromFile, loadFromStream, saveToMemory /// //////////////////////////////////////////////////////////// - [[nodiscard]] static std::optional createFromMemory(const void* data, std::size_t size); + [[nodiscard]] bool loadFromMemory(const void* data, std::size_t size); //////////////////////////////////////////////////////////// /// \brief Load the image from a custom stream @@ -205,12 +204,12 @@ class SFML_GRAPHICS_API Image /// /// \param stream Source stream to read from /// - /// \return Image if loading was successful, `std::nullopt` otherwise + /// \return True if loading was successful /// - /// \see createFromFile, createFromMemory + /// \see loadFromFile, loadFromMemory /// //////////////////////////////////////////////////////////// - [[nodiscard]] static std::optional createFromStream(InputStream& stream); + [[nodiscard]] bool loadFromStream(InputStream& stream); //////////////////////////////////////////////////////////// /// \brief Save the image to a file on disk @@ -224,7 +223,7 @@ class SFML_GRAPHICS_API Image /// /// \return True if saving was successful /// - /// \see create, createFromFile, createFromMemory + /// \see saveToMemory, loadFromFile /// //////////////////////////////////////////////////////////// [[nodiscard]] bool saveToFile(const std::filesystem::path& filename) const; @@ -242,7 +241,7 @@ class SFML_GRAPHICS_API Image /// \return Buffer with encoded data if saving was successful, /// otherwise std::nullopt /// - /// \see create, createFromFile, createFromMemory, saveToFile + /// \see saveToFile, loadFromMemory /// //////////////////////////////////////////////////////////// [[nodiscard]] std::optional> saveToMemory(std::string_view format) const; @@ -386,7 +385,7 @@ class SFML_GRAPHICS_API Image /// channels -- just like a sf::Color. /// All the functions that return an array of pixels follow /// 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. /// /// A sf::Image can be copied, but it is a heavy resource and @@ -396,7 +395,7 @@ class SFML_GRAPHICS_API Image /// Usage example: /// \code /// // 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 /// sf::Image image({20, 20}, sf::Color::Black); diff --git a/include/SFML/Graphics/RenderTexture.hpp b/include/SFML/Graphics/RenderTexture.hpp index eb440c2fab..fc2d6a910b 100644 --- a/include/SFML/Graphics/RenderTexture.hpp +++ b/include/SFML/Graphics/RenderTexture.hpp @@ -37,7 +37,6 @@ #include #include -#include namespace sf @@ -64,6 +63,25 @@ class SFML_GRAPHICS_API RenderTexture : public RenderTarget //////////////////////////////////////////////////////////// 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 /// @@ -108,29 +126,10 @@ class SFML_GRAPHICS_API RenderTexture : public RenderTarget /// \param size Width and height of the render-texture /// \param settings Additional settings for the underlying OpenGL texture and context /// - /// \return True if resizing has been successful - /// - //////////////////////////////////////////////////////////// - [[nodiscard]] bool resize(Vector2u size, const ContextSettings& settings = ContextSettings()); - - //////////////////////////////////////////////////////////// - /// \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` + /// \return True if resizing has been successful, false if it failed /// //////////////////////////////////////////////////////////// - [[nodiscard]] static std::optional create(Vector2u size, const ContextSettings& settings = {}); + [[nodiscard]] bool resize(Vector2u size, const ContextSettings& settings = {}); //////////////////////////////////////////////////////////// /// \brief Get the maximum anti-aliasing level supported by the system @@ -302,7 +301,7 @@ class SFML_GRAPHICS_API RenderTexture : public RenderTarget /// sf::RenderWindow window(sf::VideoMode({800, 600}), "SFML window"); /// /// // Create a new render-texture -/// auto texture = sf::RenderTexture::create({500, 500}).value(); +/// sf::RenderTexture texture({500, 500}); /// /// // The main loop /// while (window.isOpen()) diff --git a/include/SFML/Graphics/RenderWindow.hpp b/include/SFML/Graphics/RenderWindow.hpp index 962bece766..bd4ce969f7 100644 --- a/include/SFML/Graphics/RenderWindow.hpp +++ b/include/SFML/Graphics/RenderWindow.hpp @@ -87,7 +87,7 @@ class SFML_GRAPHICS_API RenderWindow : public Window, public RenderTarget const String& title, std::uint32_t style = Style::Default, State state = State::Windowed, - const ContextSettings& settings = ContextSettings()); + const ContextSettings& settings = {}); //////////////////////////////////////////////////////////// /// \brief Construct a new window @@ -106,7 +106,7 @@ class SFML_GRAPHICS_API RenderWindow : public Window, public RenderTarget /// \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 @@ -124,7 +124,7 @@ class SFML_GRAPHICS_API RenderWindow : public Window, public RenderTarget /// \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 @@ -266,9 +266,9 @@ class SFML_GRAPHICS_API RenderWindow : public Window, public RenderTarget /// sf::RenderWindow window(sf::VideoMode({800, 600}), "SFML OpenGL"); /// /// // 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); -/// const auto font = sf::Font::createFromFile("arial.ttf").value(); +/// const sf::Font font("arial.ttf"); /// sf::Text text(font); /// ... /// diff --git a/include/SFML/Graphics/Shader.hpp b/include/SFML/Graphics/Shader.hpp index 9133b0ec87..119cb1df03 100644 --- a/include/SFML/Graphics/Shader.hpp +++ b/include/SFML/Graphics/Shader.hpp @@ -34,7 +34,6 @@ #include #include -#include #include #include #include @@ -127,9 +126,9 @@ class SFML_GRAPHICS_API Shader : GlResource Shader& operator=(Shader&& right) noexcept; //////////////////////////////////////////////////////////// - /// \brief Load the vertex, geometry or fragment shader from a file + /// \brief Construct from a shader file /// - /// This function loads a single shader, vertex, geometry or + /// 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 @@ -140,17 +139,17 @@ class SFML_GRAPHICS_API Shader : GlResource /// \param filename Path of the vertex, geometry or fragment shader file to load /// \param type Type of shader (vertex, geometry or fragment) /// - /// \return True if loading succeeded, false if it failed + /// \throws std::runtime_error if loading was unsuccessful /// - /// \see loadFromMemory, loadFromStream + /// \see loadFromFile, loadFromMemory, loadFromStream /// //////////////////////////////////////////////////////////// - [[nodiscard]] bool loadFromFile(const std::filesystem::path& filename, Type type); + Shader(const std::filesystem::path& filename, Type type); //////////////////////////////////////////////////////////// - /// \brief Load both the vertex and fragment shaders from files + /// \brief Construct from vertex and fragment shader files /// - /// This function loads both the vertex and the fragment + /// 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 @@ -161,18 +160,17 @@ class SFML_GRAPHICS_API Shader : GlResource /// \param vertexShaderFilename Path of the vertex shader file to load /// \param fragmentShaderFilename Path of the fragment shader file to load /// - /// \return True if loading succeeded, false if it failed + /// \throws std::runtime_error if loading was unsuccessful /// - /// \see loadFromMemory, loadFromStream + /// \see loadFromFile, loadFromMemory, loadFromStream /// //////////////////////////////////////////////////////////// - [[nodiscard]] bool loadFromFile(const std::filesystem::path& vertexShaderFilename, - const std::filesystem::path& fragmentShaderFilename); + Shader(const std::filesystem::path& vertexShaderFilename, const std::filesystem::path& fragmentShaderFilename); //////////////////////////////////////////////////////////// - /// \brief Load the vertex, geometry and fragment shaders from files + /// \brief Construct from vertex, geometry and fragment shader files /// - /// This function loads the vertex, geometry and fragment + /// 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 @@ -184,19 +182,19 @@ class SFML_GRAPHICS_API Shader : GlResource /// \param geometryShaderFilename Path of the geometry shader file to load /// \param fragmentShaderFilename Path of the fragment shader file to load /// - /// \return True if loading succeeded, false if it failed + /// \throws std::runtime_error if loading was unsuccessful /// - /// \see loadFromMemory, loadFromStream + /// \see loadFromFile, loadFromMemory, loadFromStream /// //////////////////////////////////////////////////////////// - [[nodiscard]] bool loadFromFile(const std::filesystem::path& vertexShaderFilename, - const std::filesystem::path& geometryShaderFilename, - const std::filesystem::path& fragmentShaderFilename); + Shader(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 + /// \brief Construct from shader in memory /// - /// This function loads a single shader, vertex, geometry + /// 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; @@ -206,17 +204,17 @@ class SFML_GRAPHICS_API Shader : GlResource /// \param shader String containing the source code of the shader /// \param type Type of shader (vertex, geometry or fragment) /// - /// \return True if loading succeeded, false if it failed + /// \throws std::runtime_error if loading was unsuccessful /// - /// \see loadFromFile, loadFromStream + /// \see loadFromFile, loadFromMemory, loadFromStream /// //////////////////////////////////////////////////////////// - [[nodiscard]] bool loadFromMemory(std::string_view shader, Type type); + Shader(std::string_view shader, Type type); //////////////////////////////////////////////////////////// - /// \brief Load both the vertex and fragment shaders from source codes in memory + /// \brief Construct from vertex and fragment shaders in memory /// - /// This function loads both the vertex and the fragment + /// 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 @@ -227,17 +225,17 @@ class SFML_GRAPHICS_API Shader : GlResource /// \param vertexShader String containing the source code of the vertex shader /// \param fragmentShader String containing the source code of the fragment shader /// - /// \return True if loading succeeded, false if it failed + /// \throws std::runtime_error if loading was unsuccessful /// - /// \see loadFromFile, loadFromStream + /// \see loadFromFile, loadFromMemory, loadFromStream /// //////////////////////////////////////////////////////////// - [[nodiscard]] bool loadFromMemory(std::string_view vertexShader, std::string_view fragmentShader); + Shader(std::string_view vertexShader, std::string_view fragmentShader); //////////////////////////////////////////////////////////// - /// \brief Load the vertex, geometry and fragment shaders from source codes in memory + /// \brief Construct from vertex, geometry and fragment shaders in memory /// - /// This function loads the vertex, geometry and fragment + /// 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 @@ -249,19 +247,17 @@ class SFML_GRAPHICS_API Shader : GlResource /// \param geometryShader String containing the source code of the geometry shader /// \param fragmentShader String containing the source code of the fragment shader /// - /// \return True if loading succeeded, false if it failed + /// \throws std::runtime_error if loading was unsuccessful /// - /// \see loadFromFile, loadFromStream + /// \see loadFromFile, loadFromMemory, loadFromStream /// //////////////////////////////////////////////////////////// - [[nodiscard]] bool loadFromMemory(std::string_view vertexShader, - std::string_view geometryShader, - std::string_view fragmentShader); + Shader(std::string_view vertexShader, std::string_view geometryShader, std::string_view fragmentShader); //////////////////////////////////////////////////////////// - /// \brief Load the vertex, geometry or fragment shader from a custom stream + /// \brief Construct from a shader stream /// - /// This function loads a single shader, vertex, geometry + /// 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; @@ -271,17 +267,17 @@ class SFML_GRAPHICS_API Shader : GlResource /// \param stream Source stream to read from /// \param type Type of shader (vertex, geometry or fragment) /// - /// \return True if loading succeeded, false if it failed + /// \throws std::runtime_error if loading was unsuccessful /// - /// \see loadFromFile, loadFromMemory + /// \see loadFromFile, loadFromMemory, loadFromStream /// //////////////////////////////////////////////////////////// - [[nodiscard]] bool loadFromStream(InputStream& stream, Type type); + Shader(InputStream& stream, Type type); //////////////////////////////////////////////////////////// - /// \brief Load both the vertex and fragment shaders from custom streams + /// \brief Construct from vertex and fragment shader streams /// - /// This function loads both the vertex and the fragment + /// 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. @@ -292,17 +288,17 @@ class SFML_GRAPHICS_API Shader : GlResource /// \param vertexShaderStream Source stream to read the vertex shader from /// \param fragmentShaderStream Source stream to read the fragment shader from /// - /// \return True if loading succeeded, false if it failed + /// \throws std::runtime_error if loading was unsuccessful /// - /// \see loadFromFile, loadFromMemory + /// \see loadFromFile, loadFromMemory, loadFromStream /// //////////////////////////////////////////////////////////// - [[nodiscard]] bool loadFromStream(InputStream& vertexShaderStream, InputStream& fragmentShaderStream); + Shader(InputStream& vertexShaderStream, InputStream& fragmentShaderStream); //////////////////////////////////////////////////////////// - /// \brief Load the vertex, geometry and fragment shaders from custom streams + /// \brief Construct from vertex, geometry and fragment shader streams /// - /// This function loads the vertex, geometry and fragment + /// 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. @@ -314,14 +310,12 @@ class SFML_GRAPHICS_API Shader : GlResource /// \param geometryShaderStream Source stream to read the geometry shader from /// \param fragmentShaderStream Source stream to read the fragment shader from /// - /// \return True if loading succeeded, false if it failed + /// \throws std::runtime_error if loading was unsuccessful /// - /// \see loadFromFile, loadFromMemory + /// \see loadFromFile, loadFromMemory, loadFromStream /// //////////////////////////////////////////////////////////// - [[nodiscard]] bool loadFromStream(InputStream& vertexShaderStream, - InputStream& geometryShaderStream, - InputStream& fragmentShaderStream); + Shader(InputStream& vertexShaderStream, InputStream& geometryShaderStream, InputStream& fragmentShaderStream); //////////////////////////////////////////////////////////// /// \brief Load the vertex, geometry or fragment shader from a file @@ -337,12 +331,12 @@ class SFML_GRAPHICS_API Shader : GlResource /// \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 + /// \return True if loading succeeded, false if it failed /// - /// \see createFromMemory, createFromStream + /// \see loadFromMemory, loadFromStream /// //////////////////////////////////////////////////////////// - [[nodiscard]] static std::optional createFromFile(const std::filesystem::path& filename, Type type); + [[nodiscard]] bool loadFromFile(const std::filesystem::path& filename, Type type); //////////////////////////////////////////////////////////// /// \brief Load both the vertex and fragment shaders from files @@ -358,13 +352,13 @@ class SFML_GRAPHICS_API Shader : GlResource /// \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 + /// \return True if loading succeeded, false if it failed /// - /// \see createFromMemory, createFromStream + /// \see loadFromMemory, loadFromStream /// //////////////////////////////////////////////////////////// - [[nodiscard]] static std::optional createFromFile(const std::filesystem::path& vertexShaderFilename, - const std::filesystem::path& fragmentShaderFilename); + [[nodiscard]] bool loadFromFile(const std::filesystem::path& vertexShaderFilename, + const std::filesystem::path& fragmentShaderFilename); //////////////////////////////////////////////////////////// /// \brief Load the vertex, geometry and fragment shaders from files @@ -381,14 +375,14 @@ class SFML_GRAPHICS_API Shader : GlResource /// \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 + /// \return True if loading succeeded, false if it failed /// - /// \see createFromMemory, createFromStream + /// \see loadFromMemory, loadFromStream /// //////////////////////////////////////////////////////////// - [[nodiscard]] static std::optional createFromFile(const std::filesystem::path& vertexShaderFilename, - const std::filesystem::path& geometryShaderFilename, - const std::filesystem::path& fragmentShaderFilename); + [[nodiscard]] bool loadFromFile(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 @@ -403,12 +397,12 @@ class SFML_GRAPHICS_API Shader : GlResource /// \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 + /// \return True if loading succeeded, false if it failed /// - /// \see createFromFile, createFromStream + /// \see loadFromFile, loadFromStream /// //////////////////////////////////////////////////////////// - [[nodiscard]] static std::optional createFromMemory(std::string_view shader, Type type); + [[nodiscard]] bool loadFromMemory(std::string_view shader, Type type); //////////////////////////////////////////////////////////// /// \brief Load both the vertex and fragment shaders from source codes in memory @@ -424,12 +418,12 @@ class SFML_GRAPHICS_API Shader : GlResource /// \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 + /// \return True if loading succeeded, false if it failed /// - /// \see createFromFile, createFromStream + /// \see loadFromFile, loadFromStream /// //////////////////////////////////////////////////////////// - [[nodiscard]] static std::optional createFromMemory(std::string_view vertexShader, std::string_view fragmentShader); + [[nodiscard]] bool loadFromMemory(std::string_view vertexShader, std::string_view fragmentShader); //////////////////////////////////////////////////////////// /// \brief Load the vertex, geometry and fragment shaders from source codes in memory @@ -446,14 +440,14 @@ class SFML_GRAPHICS_API Shader : GlResource /// \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 + /// \return True if loading succeeded, false if it failed /// - /// \see createFromFile, createFromStream + /// \see loadFromFile, loadFromStream /// //////////////////////////////////////////////////////////// - [[nodiscard]] static std::optional createFromMemory(std::string_view vertexShader, - std::string_view geometryShader, - std::string_view fragmentShader); + [[nodiscard]] bool loadFromMemory(std::string_view vertexShader, + std::string_view geometryShader, + std::string_view fragmentShader); //////////////////////////////////////////////////////////// /// \brief Load the vertex, geometry or fragment shader from a custom stream @@ -468,12 +462,12 @@ class SFML_GRAPHICS_API Shader : GlResource /// \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 + /// \return True if loading succeeded, false if it failed /// - /// \see createFromFile, createFromMemory + /// \see loadFromFile, loadFromMemory /// //////////////////////////////////////////////////////////// - [[nodiscard]] static std::optional createFromStream(InputStream& stream, Type type); + [[nodiscard]] bool loadFromStream(InputStream& stream, Type type); //////////////////////////////////////////////////////////// /// \brief Load both the vertex and fragment shaders from custom streams @@ -489,13 +483,12 @@ class SFML_GRAPHICS_API Shader : GlResource /// \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 + /// \return True if loading succeeded, false if it failed /// - /// \see createFromFile, createFromMemory + /// \see loadFromFile, loadFromMemory /// //////////////////////////////////////////////////////////// - [[nodiscard]] static std::optional createFromStream(InputStream& vertexShaderStream, - InputStream& fragmentShaderStream); + [[nodiscard]] bool loadFromStream(InputStream& vertexShaderStream, InputStream& fragmentShaderStream); //////////////////////////////////////////////////////////// /// \brief Load the vertex, geometry and fragment shaders from custom streams @@ -512,14 +505,14 @@ class SFML_GRAPHICS_API Shader : GlResource /// \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 + /// \return True if loading succeeded, false if it failed /// - /// \see createFromFile, createFromMemory + /// \see loadFromFile, loadFromMemory /// //////////////////////////////////////////////////////////// - [[nodiscard]] static std::optional createFromStream(InputStream& vertexShaderStream, - InputStream& geometryShaderStream, - InputStream& fragmentShaderStream); + [[nodiscard]] bool loadFromStream(InputStream& vertexShaderStream, + InputStream& geometryShaderStream, + InputStream& fragmentShaderStream); //////////////////////////////////////////////////////////// /// \brief Specify value for \p float uniform diff --git a/include/SFML/Graphics/Sprite.hpp b/include/SFML/Graphics/Sprite.hpp index 2b363a1852..c35dee121d 100644 --- a/include/SFML/Graphics/Sprite.hpp +++ b/include/SFML/Graphics/Sprite.hpp @@ -261,7 +261,7 @@ class SFML_GRAPHICS_API Sprite : public Drawable, public Transformable /// Usage example: /// \code /// // Load a texture -/// const auto texture = sf::Texture::createFromFile("texture.png").value(); +/// const sf::Texture texture("texture.png"); /// /// // Create a sprite /// sf::Sprite sprite(texture); diff --git a/include/SFML/Graphics/Text.hpp b/include/SFML/Graphics/Text.hpp index d0a1dad632..9707c66424 100644 --- a/include/SFML/Graphics/Text.hpp +++ b/include/SFML/Graphics/Text.hpp @@ -469,7 +469,7 @@ class SFML_GRAPHICS_API Text : public Drawable, public Transformable /// Usage example: /// \code /// // Open a font -/// const auto font = sf::Font::createFromFile("arial.ttf").value(); +/// const sf::Font font("arial.ttf"); /// /// // Create a text /// sf::Text text(font, "hello"); diff --git a/include/SFML/Graphics/Texture.hpp b/include/SFML/Graphics/Texture.hpp index c497d3b0fd..d83f73b69b 100644 --- a/include/SFML/Graphics/Texture.hpp +++ b/include/SFML/Graphics/Texture.hpp @@ -37,7 +37,6 @@ #include #include -#include #include #include @@ -61,6 +60,8 @@ class SFML_GRAPHICS_API Texture : GlResource /// /// Creates a texture with width 0 and height 0. /// + /// \see resize + /// //////////////////////////////////////////////////////////// Texture(); @@ -97,29 +98,23 @@ class SFML_GRAPHICS_API Texture : GlResource Texture& operator=(Texture&&) noexcept; //////////////////////////////////////////////////////////// - /// \brief Resize the texture + /// \brief Construct the texture from a file on disk /// - /// If this function fails, the texture is left unchanged. + /// The maximum size for a texture depends on the graphics + /// driver and can be retrieved with the getMaximumSize function. /// - /// \param size Width and height of the texture - /// \param sRgb True to enable sRGB conversion, false to disable it + /// \param filename Path of the image file to load + /// \param sRgb True to enable sRGB conversion, false to disable it /// - /// \return True if resizing was successful + /// \throws std::runtime_error if loading was unsuccessful + /// + /// \see loadFromFile, loadFromMemory, loadFromStream, loadFromImage /// //////////////////////////////////////////////////////////// - [[nodiscard]] bool resize(Vector2u size, bool sRgb = false); + explicit Texture(const std::filesystem::path& filename, bool sRgb = false); //////////////////////////////////////////////////////////// - /// \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 + /// \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 @@ -130,30 +125,36 @@ class SFML_GRAPHICS_API Texture : GlResource /// 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 True if loading was successful + /// \throws std::runtime_error if loading was unsuccessful /// - /// \see loadFromMemory, loadFromStream, loadFromImage + /// \see loadFromFile, loadFromMemory, loadFromStream, loadFromImage /// //////////////////////////////////////////////////////////// - [[nodiscard]] bool loadFromFile(const std::filesystem::path& filename, bool sRgb = false, const IntRect& area = IntRect()); + Texture(const std::filesystem::path& filename, bool sRgb, const IntRect& area); //////////////////////////////////////////////////////////// - /// \brief Load the texture from a file in memory + /// \brief Construct 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 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 @@ -164,31 +165,36 @@ class SFML_GRAPHICS_API Texture : GlResource /// 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 True if loading was successful + /// \throws std::runtime_error if loading was unsuccessful /// - /// \see loadFromFile, loadFromStream, loadFromImage + /// \see loadFromFile, loadFromMemory, loadFromStream, loadFromImage /// //////////////////////////////////////////////////////////// - [[nodiscard]] bool loadFromMemory(const void* data, std::size_t size, bool sRgb = false, const IntRect& area = IntRect()); + Texture(const void* data, std::size_t size, bool sRgb, const IntRect& area); //////////////////////////////////////////////////////////// - /// \brief Load the texture from a custom stream + /// \brief Construct 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 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 @@ -199,54 +205,78 @@ class SFML_GRAPHICS_API Texture : GlResource /// 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 True if loading was successful + /// \throws std::runtime_error if loading was unsuccessful /// - /// \see loadFromFile, loadFromMemory, loadFromImage + /// \see loadFromFile, loadFromMemory, loadFromStream, loadFromImage /// //////////////////////////////////////////////////////////// - [[nodiscard]] bool loadFromStream(InputStream& stream, bool sRgb = false, const IntRect& area = IntRect()); + Texture(InputStream& stream, bool sRgb, const IntRect& area); //////////////////////////////////////////////////////////// - /// \brief Load the texture from an image + /// \brief Construct 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). + /// 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. /// - /// 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 True if loading was successful + /// \throws std::runtime_error if loading was unsuccessful /// - /// \see loadFromFile, loadFromMemory + /// \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 /// //////////////////////////////////////////////////////////// - [[nodiscard]] bool loadFromImage(const Image& image, bool sRgb = false, const IntRect& area = IntRect()); + explicit Texture(Vector2u size, bool sRgb = false); //////////////////////////////////////////////////////////// - /// \brief Create a texture + /// \brief Resize the texture + /// + /// If this function fails, the texture is left unchanged. /// /// \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` + /// \return True if resizing was successful, false if it failed /// //////////////////////////////////////////////////////////// - [[nodiscard]] static std::optional create(Vector2u size, bool sRgb = false); + [[nodiscard]] bool resize(Vector2u size, bool sRgb = false); //////////////////////////////////////////////////////////// /// \brief Load the texture from a file on disk @@ -266,14 +296,12 @@ class SFML_GRAPHICS_API Texture : GlResource /// \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` + /// \return True if loading was successful, false if it failed /// - /// \see createFromMemory, createFromStream, createFromImage + /// \see loadFromMemory, loadFromStream, loadFromImage /// //////////////////////////////////////////////////////////// - [[nodiscard]] static std::optional createFromFile(const std::filesystem::path& filename, - bool sRgb = false, - const IntRect& area = {}); + [[nodiscard]] bool loadFromFile(const std::filesystem::path& filename, bool sRgb = false, const IntRect& area = {}); //////////////////////////////////////////////////////////// /// \brief Load the texture from a file in memory @@ -294,16 +322,12 @@ class SFML_GRAPHICS_API Texture : GlResource /// \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` + /// \return True if loading was successful, false if it failed /// - /// \see createFromFile, createFromStream, createFromImage + /// \see loadFromFile, loadFromStream, loadFromImage /// //////////////////////////////////////////////////////////// - [[nodiscard]] static std::optional createFromMemory( - const void* data, - std::size_t size, - bool sRgb = false, - const IntRect& area = {}); + [[nodiscard]] bool loadFromMemory(const void* data, std::size_t size, bool sRgb = false, const IntRect& area = {}); //////////////////////////////////////////////////////////// /// \brief Load the texture from a custom stream @@ -323,14 +347,12 @@ class SFML_GRAPHICS_API Texture : GlResource /// \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` + /// \return True if loading was successful, false if it failed /// - /// \see createFromFile, createFromMemory, createFromImage + /// \see loadFromFile, loadFromMemory, loadFromImage /// //////////////////////////////////////////////////////////// - [[nodiscard]] static std::optional createFromStream(InputStream& stream, - bool sRgb = false, - const IntRect& area = {}); + [[nodiscard]] bool loadFromStream(InputStream& stream, bool sRgb = false, const IntRect& area = {}); //////////////////////////////////////////////////////////// /// \brief Load the texture from an image @@ -347,15 +369,15 @@ class SFML_GRAPHICS_API Texture : GlResource /// 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 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` + /// \return True if loading was successful, false if it failed /// - /// \see createFromFile, createFromMemory + /// \see loadFromFile, loadFromMemory /// //////////////////////////////////////////////////////////// - [[nodiscard]] static std::optional createFromImage(const Image& image, bool sRgb = false, const IntRect& area = {}); + [[nodiscard]] bool loadFromImage(const Image& image, bool sRgb = false, const IntRect& area = {}); //////////////////////////////////////////////////////////// /// \brief Return the size of the texture @@ -375,7 +397,7 @@ class SFML_GRAPHICS_API Texture : GlResource /// /// \return Image containing the texture's pixels /// - /// \see createFromImage + /// \see loadFromImage /// //////////////////////////////////////////////////////////// [[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 /// before creating the final texture, you can load your file to a /// 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 /// 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 /// /// // 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 /// 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 /// /// // 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 /// sf::Sprite sprite(texture); diff --git a/include/SFML/System/FileInputStream.hpp b/include/SFML/System/FileInputStream.hpp index 06644d17e7..3d0cae96ab 100644 --- a/include/SFML/System/FileInputStream.hpp +++ b/include/SFML/System/FileInputStream.hpp @@ -96,24 +96,24 @@ class SFML_SYSTEM_API FileInputStream : public InputStream FileInputStream& operator=(FileInputStream&&) noexcept; //////////////////////////////////////////////////////////// - /// \brief Open the stream from a file path + /// \brief Construct the stream from a file path /// /// \param filename Name of the file to open /// - /// \return True on success, false on error + /// \throws std::runtime_error on error /// //////////////////////////////////////////////////////////// - [[nodiscard]] bool open(const std::filesystem::path& filename); + explicit FileInputStream(const std::filesystem::path& filename); //////////////////////////////////////////////////////////// - /// \brief Create the stream from a file path + /// \brief Open the stream from a file path /// /// \param filename Name of the file to open /// - /// \return File input stream on success, `std::nullopt` on error + /// \return True on success, false on error /// //////////////////////////////////////////////////////////// - [[nodiscard]] static std::optional create(const std::filesystem::path& filename); + [[nodiscard]] bool open(const std::filesystem::path& filename); //////////////////////////////////////////////////////////// /// \brief Read data from the stream diff --git a/include/SFML/System/InputStream.hpp b/include/SFML/System/InputStream.hpp index 19bc9e5a8d..fa298e1778 100644 --- a/include/SFML/System/InputStream.hpp +++ b/include/SFML/System/InputStream.hpp @@ -103,12 +103,12 @@ class SFML_SYSTEM_API InputStream /// from which SFML can load resources. /// /// 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 /// have data coming from a different source (over a network, /// embedded, encrypted, compressed, etc) you can derive your /// own class from sf::InputStream and load SFML resources with -/// their createFromStream function. +/// their loadFromStream function. /// /// Usage example: /// \code @@ -142,7 +142,7 @@ class SFML_SYSTEM_API InputStream /// // Handle error... /// } /// -/// const auto texture = sf::Texture::createFromStream(stream).value(); +/// const sf::Texture texture(stream); /// /// // musics... /// sf::Music music; diff --git a/include/SFML/System/MemoryInputStream.hpp b/include/SFML/System/MemoryInputStream.hpp index 917a037e94..95a3fa925f 100644 --- a/include/SFML/System/MemoryInputStream.hpp +++ b/include/SFML/System/MemoryInputStream.hpp @@ -55,15 +55,6 @@ class SFML_SYSTEM_API MemoryInputStream : public InputStream //////////////////////////////////////////////////////////// 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 /// diff --git a/include/SFML/Window/Cursor.hpp b/include/SFML/Window/Cursor.hpp index 816cbda1b0..6207ee24ea 100644 --- a/include/SFML/Window/Cursor.hpp +++ b/include/SFML/Window/Cursor.hpp @@ -144,6 +144,55 @@ class SFML_WINDOW_API Cursor //////////////////////////////////////////////////////////// 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 /// diff --git a/include/SFML/Window/Window.hpp b/include/SFML/Window/Window.hpp index 2310c11259..0fa3e5cb09 100644 --- a/include/SFML/Window/Window.hpp +++ b/include/SFML/Window/Window.hpp @@ -89,7 +89,7 @@ class SFML_WINDOW_API Window : public WindowBase, GlResource const String& title, std::uint32_t style = Style::Default, State state = State::Windowed, - const ContextSettings& settings = ContextSettings()); + const ContextSettings& settings = {}); //////////////////////////////////////////////////////////// /// \brief Construct a new window @@ -108,7 +108,7 @@ class SFML_WINDOW_API Window : public WindowBase, GlResource /// \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 @@ -124,7 +124,7 @@ class SFML_WINDOW_API Window : public WindowBase, GlResource /// \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 diff --git a/src/SFML/Audio/InputSoundFile.cpp b/src/SFML/Audio/InputSoundFile.cpp index a6afcb79b1..97714658b3 100644 --- a/src/SFML/Audio/InputSoundFile.cpp +++ b/src/SFML/Audio/InputSoundFile.cpp @@ -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) { @@ -192,42 +216,6 @@ bool InputSoundFile::openFromStream(InputStream& stream) } -//////////////////////////////////////////////////////////// -std::optional InputSoundFile::createFromFile(const std::filesystem::path& filename) -{ - auto inputSoundFile = std::make_optional(); - - if (!inputSoundFile->openFromFile(filename)) - return std::nullopt; - - return inputSoundFile; -} - - -//////////////////////////////////////////////////////////// -std::optional InputSoundFile::createFromMemory(const void* data, std::size_t sizeInBytes) -{ - auto inputSoundFile = std::make_optional(); - - if (!inputSoundFile->openFromMemory(data, sizeInBytes)) - return std::nullopt; - - return inputSoundFile; -} - - -//////////////////////////////////////////////////////////// -std::optional InputSoundFile::createFromStream(InputStream& stream) -{ - auto inputSoundFile = std::make_optional(); - - if (!inputSoundFile->openFromStream(stream)) - return std::nullopt; - - return inputSoundFile; -} - - //////////////////////////////////////////////////////////// std::uint64_t InputSoundFile::getSampleCount() const { diff --git a/src/SFML/Audio/Music.cpp b/src/SFML/Audio/Music.cpp index 970b1106fc..5724783382 100644 --- a/src/SFML/Audio/Music.cpp +++ b/src/SFML/Audio/Music.cpp @@ -64,6 +64,30 @@ Music::Music() : m_impl(std::make_unique()) } +//////////////////////////////////////////////////////////// +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() { @@ -152,42 +176,6 @@ bool Music::openFromStream(InputStream& stream) } -//////////////////////////////////////////////////////////// -std::optional Music::createFromFile(const std::filesystem::path& filename) -{ - auto music = std::make_optional(); - - if (!music->openFromFile(filename)) - return std::nullopt; - - return music; -} - - -//////////////////////////////////////////////////////////// -std::optional Music::createFromMemory(const void* data, std::size_t sizeInBytes) -{ - auto music = std::make_optional(); - - if (!music->openFromMemory(data, sizeInBytes)) - return std::nullopt; - - return music; -} - - -//////////////////////////////////////////////////////////// -std::optional Music::createFromStream(InputStream& stream) -{ - auto music = std::make_optional(); - - if (!music->openFromStream(stream)) - return std::nullopt; - - return music; -} - - //////////////////////////////////////////////////////////// Time Music::getDuration() const { diff --git a/src/SFML/Audio/OutputSoundFile.cpp b/src/SFML/Audio/OutputSoundFile.cpp index 2b18bad1cd..eb3f59239b 100644 --- a/src/SFML/Audio/OutputSoundFile.cpp +++ b/src/SFML/Audio/OutputSoundFile.cpp @@ -36,6 +36,17 @@ namespace sf { +//////////////////////////////////////////////////////////// +OutputSoundFile::OutputSoundFile(const std::filesystem::path& filename, + unsigned int sampleRate, + unsigned int channelCount, + const std::vector& 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, unsigned int sampleRate, @@ -65,22 +76,6 @@ bool OutputSoundFile::openFromFile(const std::filesystem::path& filename, } -//////////////////////////////////////////////////////////// -std::optional OutputSoundFile::createFromFile( - const std::filesystem::path& filename, - unsigned int sampleRate, - unsigned int channelCount, - const std::vector& channelMap) -{ - auto outputSoundFile = std::make_optional(); - - if (!outputSoundFile->openFromFile(filename, sampleRate, channelCount, channelMap)) - return std::nullopt; - - return outputSoundFile; -} - - //////////////////////////////////////////////////////////// void OutputSoundFile::write(const std::int16_t* samples, std::uint64_t count) { diff --git a/src/SFML/Audio/SoundBuffer.cpp b/src/SFML/Audio/SoundBuffer.cpp index 16501555f2..6b6759e24e 100644 --- a/src/SFML/Audio/SoundBuffer.cpp +++ b/src/SFML/Audio/SoundBuffer.cpp @@ -39,6 +39,42 @@ 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& channelMap) +{ + if (!loadFromSamples(samples, sampleCount, channelCount, sampleRate, channelMap)) + throw std::runtime_error("Failed to open sound buffer from samples"); +} + + //////////////////////////////////////////////////////////// SoundBuffer::SoundBuffer(const SoundBuffer& copy) { @@ -130,59 +166,6 @@ bool SoundBuffer::loadFromSamples(const std::int16_t* samples, } -//////////////////////////////////////////////////////////// -std::optional SoundBuffer::createFromFile(const std::filesystem::path& filename) -{ - auto soundBuffer = std::make_optional(); - - if (!soundBuffer->loadFromFile(filename)) - return std::nullopt; - - return soundBuffer; -} - - -//////////////////////////////////////////////////////////// -std::optional SoundBuffer::createFromMemory(const void* data, std::size_t sizeInBytes) -{ - auto soundBuffer = std::make_optional(); - - if (!soundBuffer->loadFromMemory(data, sizeInBytes)) - return std::nullopt; - - return soundBuffer; -} - - -//////////////////////////////////////////////////////////// -std::optional SoundBuffer::createFromStream(InputStream& stream) -{ - auto soundBuffer = std::make_optional(); - - if (!soundBuffer->loadFromStream(stream)) - return std::nullopt; - - return soundBuffer; -} - - -//////////////////////////////////////////////////////////// -std::optional SoundBuffer::createFromSamples( - const std::int16_t* samples, - std::uint64_t sampleCount, - unsigned int channelCount, - unsigned int sampleRate, - const std::vector& channelMap) -{ - auto soundBuffer = std::make_optional(); - - if (!soundBuffer->loadFromSamples(samples, sampleCount, channelCount, sampleRate, channelMap)) - return std::nullopt; - - return soundBuffer; -} - - //////////////////////////////////////////////////////////// bool SoundBuffer::saveToFile(const std::filesystem::path& filename) const { diff --git a/src/SFML/Audio/SoundBufferRecorder.cpp b/src/SFML/Audio/SoundBufferRecorder.cpp index dbe02cbd81..48307e2796 100644 --- a/src/SFML/Audio/SoundBufferRecorder.cpp +++ b/src/SFML/Audio/SoundBufferRecorder.cpp @@ -48,7 +48,7 @@ SoundBufferRecorder::~SoundBufferRecorder() bool SoundBufferRecorder::onStart() { m_samples.clear(); - m_buffer = SoundBuffer(); + m_buffer = {}; return true; } diff --git a/src/SFML/Graphics/Font.cpp b/src/SFML/Graphics/Font.cpp index b26101e198..c6f9c6f121 100644 --- a/src/SFML/Graphics/Font.cpp +++ b/src/SFML/Graphics/Font.cpp @@ -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) { @@ -252,7 +276,7 @@ bool Font::openFromStream(InputStream& stream) } // 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; return false; @@ -305,42 +329,6 @@ bool Font::openFromStream(InputStream& stream) } -//////////////////////////////////////////////////////////// -std::optional Font::createFromFile(const std::filesystem::path& filename) -{ - auto font = std::make_optional(); - - if (!font->openFromFile(filename)) - return std::nullopt; - - return font; -} - - -//////////////////////////////////////////////////////////// -std::optional Font::createFromMemory(const void* data, std::size_t sizeInBytes) -{ - auto font = std::make_optional(); - - if (!font->openFromMemory(data, sizeInBytes)) - return std::nullopt; - - return font; -} - - -//////////////////////////////////////////////////////////// -std::optional Font::createFromStream(InputStream& stream) -{ - auto font = std::make_optional(); - - if (!font->openFromStream(stream)) - return std::nullopt; - - return font; -} - - //////////////////////////////////////////////////////////// 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 // Flooring is required as we use FT_KERNING_UNFITTED flag which is not quantized in 64 based grid - return std::floor( - (secondLsbDelta - firstRsbDelta + static_cast(kerning.x) + 32) / static_cast(1 << 6)); + return std::floor((secondLsbDelta - firstRsbDelta + static_cast(kerning.x) + 32) / float{1 << 6}); } // Invalid font @@ -425,7 +412,7 @@ float Font::getLineSpacing(unsigned int characterSize) const if (face && setCurrentSize(characterSize)) { - return static_cast(face->size->metrics.height) / static_cast(1 << 6); + return static_cast(face->size->metrics.height) / float{1 << 6}; } return 0.f; @@ -443,8 +430,7 @@ float Font::getUnderlinePosition(unsigned int characterSize) const if (!FT_IS_SCALABLE(face)) return static_cast(characterSize) / 10.f; - return -static_cast(FT_MulFix(face->underline_position, face->size->metrics.y_scale)) / - static_cast(1 << 6); + return -static_cast(FT_MulFix(face->underline_position, face->size->metrics.y_scale)) / float{1 << 6}; } return 0.f; @@ -462,8 +448,7 @@ float Font::getUnderlineThickness(unsigned int characterSize) const if (!FT_IS_SCALABLE(face)) return static_cast(characterSize) / 14.f; - return static_cast(FT_MulFix(face->underline_thickness, face->size->metrics.y_scale)) / - static_cast(1 << 6); + return static_cast(FT_MulFix(face->underline_thickness, face->size->metrics.y_scale)) / float{1 << 6}; } 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_Set(stroker, - static_cast(outlineThickness * static_cast(1 << 6)), + static_cast(outlineThickness * float{1 << 6}), FT_STROKER_LINECAP_ROUND, FT_STROKER_LINEJOIN_ROUND, 0); @@ -591,47 +576,41 @@ Glyph Font::loadGlyph(std::uint32_t codePoint, unsigned int characterSize, bool // Compute the glyph's advance offset glyph.advance = static_cast(bitmapGlyph->root.advance.x >> 16); if (bold) - glyph.advance += static_cast(weight) / static_cast(1 << 6); + glyph.advance += static_cast(weight) / float{1 << 6}; glyph.lsbDelta = static_cast(face->glyph->lsb_delta); glyph.rsbDelta = static_cast(face->glyph->rsb_delta); - unsigned int width = bitmap.width; - unsigned int height = bitmap.rows; + Vector2u size(bitmap.width, 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 // pollute them with pixels from neighbors const unsigned int padding = 2; - width += 2 * padding; - height += 2 * padding; + size += 2u * Vector2u(padding, padding); // Get the glyphs page corresponding to the character size Page& page = loadPage(characterSize); // 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 // of the allocated texture rectangle - glyph.textureRect.position.x += static_cast(padding); - glyph.textureRect.position.y += static_cast(padding); - glyph.textureRect.size.x -= static_cast(2 * padding); - glyph.textureRect.size.y -= static_cast(2 * padding); + glyph.textureRect.position += Vector2i(padding, padding); + glyph.textureRect.size -= 2 * Vector2i(padding, padding); // Compute the glyph's bounding box - glyph.bounds.position.x = static_cast(bitmapGlyph->left); - glyph.bounds.position.y = static_cast(-bitmapGlyph->top); - glyph.bounds.size.x = static_cast(bitmap.width); - glyph.bounds.size.y = static_cast(bitmap.rows); + glyph.bounds.position = Vector2f(Vector2i(bitmapGlyph->left, -bitmapGlyph->top)); + glyph.bounds.size = Vector2f(Vector2u(bitmap.width, bitmap.rows)); // Resize the pixel buffer to the new size and fill it with transparent white pixels - m_pixelBuffer.resize(static_cast(width) * static_cast(height) * 4); + m_pixelBuffer.resize(static_cast(size.x) * static_cast(size.y) * 4); 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) { @@ -646,12 +625,12 @@ Glyph Font::loadGlyph(std::uint32_t codePoint, unsigned int characterSize, bool if (bitmap.pixel_mode == FT_PIXEL_MODE_MONO) { // 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 - 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; } pixels += bitmap.pitch; @@ -659,13 +638,13 @@ Glyph Font::loadGlyph(std::uint32_t codePoint, unsigned int characterSize, bool } else { - // Pixels are 8 bits gray levels - for (unsigned int y = padding; y < height - padding; ++y) + // Pixels are 8 bit gray levels + 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 - 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]; } pixels += bitmap.pitch; @@ -673,11 +652,9 @@ Glyph Font::loadGlyph(std::uint32_t codePoint, unsigned int characterSize, bool } // Write the pixels to the texture - const unsigned int x = static_cast(glyph.textureRect.position.x) - padding; - const unsigned int y = static_cast(glyph.textureRect.position.y) - padding; - const unsigned int w = static_cast(glyph.textureRect.size.x) + 2 * padding; - const unsigned int h = static_cast(glyph.textureRect.size.y) + 2 * padding; - page.texture.update(m_pixelBuffer.data(), {w, h}, {x, y}); + const auto dest = Vector2u(glyph.textureRect.position) - Vector2u(padding, padding); + const auto updateSize = Vector2u(glyph.textureRect.size) + 2u * Vector2u(padding, padding); + page.texture.update(m_pixelBuffer.data(), updateSize, dest); } // Delete the FT glyph diff --git a/src/SFML/Graphics/Image.cpp b/src/SFML/Graphics/Image.cpp index ece5614d6e..9d9e9228cc 100644 --- a/src/SFML/Graphics/Image.cpp +++ b/src/SFML/Graphics/Image.cpp @@ -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) { @@ -257,7 +281,7 @@ bool Image::loadFromStream(InputStream& stream) m_pixels.clear(); // 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; return false; @@ -292,42 +316,6 @@ bool Image::loadFromStream(InputStream& stream) } -//////////////////////////////////////////////////////////// -std::optional Image::createFromFile(const std::filesystem::path& filename) -{ - auto image = std::make_optional(); - - if (!image->loadFromFile(filename)) - return std::nullopt; - - return image; -} - - -//////////////////////////////////////////////////////////// -std::optional Image::createFromMemory(const void* data, std::size_t size) -{ - auto image = std::make_optional(); - - if (!image->loadFromMemory(data, size)) - return std::nullopt; - - return image; -} - - -//////////////////////////////////////////////////////////// -std::optional Image::createFromStream(InputStream& stream) -{ - auto image = std::make_optional(); - - if (!image->loadFromStream(stream)) - return std::nullopt; - - return image; -} - - //////////////////////////////////////////////////////////// bool Image::saveToFile(const std::filesystem::path& filename) const { diff --git a/src/SFML/Graphics/RenderTexture.cpp b/src/SFML/Graphics/RenderTexture.cpp index 4b83d86894..f93b393b87 100644 --- a/src/SFML/Graphics/RenderTexture.cpp +++ b/src/SFML/Graphics/RenderTexture.cpp @@ -43,6 +43,14 @@ namespace sf 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; @@ -96,18 +104,6 @@ bool RenderTexture::resize(Vector2u size, const ContextSettings& settings) } -//////////////////////////////////////////////////////////// -std::optional RenderTexture::create(Vector2u size, const ContextSettings& settings) -{ - auto renderTexture = std::make_optional(); - - if (!renderTexture->resize(size, settings)) - return std::nullopt; - - return renderTexture; -} - - //////////////////////////////////////////////////////////// unsigned int RenderTexture::getMaximumAntialiasingLevel() { @@ -169,26 +165,26 @@ bool RenderTexture::setActive(bool active) //////////////////////////////////////////////////////////// void RenderTexture::display() { - if (m_impl) + if (!m_impl) + return; + + if (priv::RenderTextureImplFBO::isAvailable()) { - 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 - m_impl->updateTexture(m_texture.m_texture); - m_texture.m_pixelsFlipped = true; - m_texture.invalidateMipmap(); + // 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 + 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 { - assert(m_impl && "Must call RenderTexture::create first"); + assert(m_impl && "RenderTexture::isSrgb() Must first initialize render texture"); return m_impl->isSrgb(); } diff --git a/src/SFML/Graphics/Shader.cpp b/src/SFML/Graphics/Shader.cpp index a801c093e7..fff90a1de9 100644 --- a/src/SFML/Graphics/Shader.cpp +++ b/src/SFML/Graphics/Shader.cpp @@ -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() { @@ -455,121 +529,6 @@ bool Shader::loadFromStream(InputStream& vertexShaderStream, InputStream& geomet } -//////////////////////////////////////////////////////////// -std::optional Shader::createFromFile(const std::filesystem::path& filename, Type type) -{ - auto shader = std::make_optional(); - - if (!shader->loadFromFile(filename, type)) - return std::nullopt; - - return shader; -} - - -//////////////////////////////////////////////////////////// -std::optional Shader::createFromFile(const std::filesystem::path& vertexShaderFilename, - const std::filesystem::path& fragmentShaderFilename) -{ - auto shader = std::make_optional(); - - if (!shader->loadFromFile(vertexShaderFilename, fragmentShaderFilename)) - return std::nullopt; - - return shader; -} - - -//////////////////////////////////////////////////////////// -std::optional Shader::createFromFile(const std::filesystem::path& vertexShaderFilename, - const std::filesystem::path& geometryShaderFilename, - const std::filesystem::path& fragmentShaderFilename) -{ - auto shader = std::make_optional(); - - if (!shader->loadFromFile(vertexShaderFilename, geometryShaderFilename, fragmentShaderFilename)) - return std::nullopt; - - return shader; -} - - -//////////////////////////////////////////////////////////// -std::optional Shader::createFromMemory(std::string_view shader, Type type) -{ - auto newShader = std::make_optional(); - - if (!newShader->loadFromMemory(shader, type)) - return std::nullopt; - - return newShader; -} - - -//////////////////////////////////////////////////////////// -std::optional Shader::createFromMemory(std::string_view vertexShader, std::string_view fragmentShader) -{ - auto shader = std::make_optional(); - - if (!shader->loadFromMemory(vertexShader, fragmentShader)) - return std::nullopt; - - return shader; -} - - -//////////////////////////////////////////////////////////// -std::optional Shader::createFromMemory(std::string_view vertexShader, - std::string_view geometryShader, - std::string_view fragmentShader) -{ - auto shader = std::make_optional(); - - if (!shader->loadFromMemory(vertexShader, geometryShader, fragmentShader)) - return std::nullopt; - - return shader; -} - - -//////////////////////////////////////////////////////////// -std::optional Shader::createFromStream(InputStream& stream, Type type) -{ - auto shader = std::make_optional(); - - if (!shader->loadFromStream(stream, type)) - return std::nullopt; - - return shader; -} - - -//////////////////////////////////////////////////////////// -std::optional Shader::createFromStream(InputStream& vertexShaderStream, InputStream& fragmentShaderStream) -{ - auto shader = std::make_optional(); - - if (!shader->loadFromStream(vertexShaderStream, fragmentShaderStream)) - return std::nullopt; - - return shader; -} - - -//////////////////////////////////////////////////////////// -std::optional Shader::createFromStream(InputStream& vertexShaderStream, - InputStream& geometryShaderStream, - InputStream& fragmentShaderStream) -{ - auto shader = std::make_optional(); - - if (!shader->loadFromStream(vertexShaderStream, geometryShaderStream, fragmentShaderStream)) - return std::nullopt; - - return shader; -} - - //////////////////////////////////////////////////////////// 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) { - if (m_shaderProgram) - { - const TransientContextLock lock; + if (!m_shaderProgram) + return; + + const TransientContextLock lock; - // Find the location of the variable in the shader - const int location = getUniformLocation(name); - if (location != -1) + // Find the location of the variable in the shader + const int location = getUniformLocation(name); + if (location != -1) + { + // Store the location -> texture mapping + const auto it = m_textures.find(location); + if (it == m_textures.end()) { - // Store the location -> texture mapping - const auto it = m_textures.find(location); - if (it == m_textures.end()) - { - // New entry, make sure there are enough texture units - if (m_textures.size() + 1 >= getMaxTextureUnits()) - { - err() << "Impossible to use texture " << std::quoted(name) - << " for shader: all available texture units are used" << std::endl; - return; - } - - m_textures[location] = &texture; - } - else + // New entry, make sure there are enough texture units + if (m_textures.size() + 1 >= getMaxTextureUnits()) { - // Location already used, just replace the texture - it->second = &texture; + err() << "Impossible to use texture " << std::quoted(name) + << " for shader: all available texture units are used" << std::endl; + return; } + + m_textures[location] = &texture; + } + else + { + // Location already used, just replace the 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) { - if (m_shaderProgram) - { - const TransientContextLock lock; + if (!m_shaderProgram) + return; - // Find the location of the variable in the shader - m_currentTexture = getUniformLocation(name); - } + const TransientContextLock lock; + + // Find the location of the variable in the shader + m_currentTexture = getUniformLocation(name); } @@ -1078,154 +1037,152 @@ int Shader::getUniformLocation(const std::string& name) namespace sf { //////////////////////////////////////////////////////////// -Shader::~Shader() = default; +Shader::Shader(const std::filesystem::path& /* filename */, Type /* type */) +{ + throw std::runtime_error("Shaders are not supported with OpenGL ES 1"); +} //////////////////////////////////////////////////////////// -Shader::Shader(Shader&& source) noexcept = default; +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::operator=(Shader&& right) noexcept = default; +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"); +} //////////////////////////////////////////////////////////// -bool Shader::loadFromFile(const std::filesystem::path& /* filename */, Type /* type */) +Shader::Shader(std::string_view /* shader */, Type /* type */) { - return false; + throw std::runtime_error("Shaders are not supported with OpenGL ES 1"); } //////////////////////////////////////////////////////////// -bool Shader::loadFromFile(const std::filesystem::path& /* vertexShaderFilename */, - const std::filesystem::path& /* fragmentShaderFilename */) +Shader::Shader(std::string_view /* vertexShader */, std::string_view /* fragmentShader */) { - return false; + throw std::runtime_error("Shaders are not supported with OpenGL ES 1"); } //////////////////////////////////////////////////////////// -bool Shader::loadFromFile(const std::filesystem::path& /* vertexShaderFilename */, - const std::filesystem::path& /* geometryShaderFilename */, - const std::filesystem::path& /* fragmentShaderFilename */) +Shader::Shader(std::string_view /* vertexShader */, std::string_view /* geometryShader */, std::string_view /* fragmentShader */) { - return false; + throw std::runtime_error("Shaders are not supported with OpenGL ES 1"); } //////////////////////////////////////////////////////////// -bool Shader::loadFromMemory(std::string_view /* shader */, Type /* type */) +Shader::Shader(InputStream& /* stream */, Type /* type */) { - return false; + throw std::runtime_error("Shaders are not supported with OpenGL ES 1"); } //////////////////////////////////////////////////////////// -bool Shader::loadFromMemory(std::string_view /* vertexShader */, std::string_view /* fragmentShader */) +Shader::Shader(InputStream& /* vertexShaderStream */, InputStream& /* fragmentShaderStream */) { - return false; + throw std::runtime_error("Shaders are not supported with OpenGL ES 1"); } //////////////////////////////////////////////////////////// -bool Shader::loadFromMemory(std::string_view /* vertexShader */, - std::string_view /* geometryShader */, - std::string_view /* fragmentShader */) +Shader::Shader(InputStream& /* vertexShaderStream */, + InputStream& /* geometryShaderStream */, + InputStream& /* fragmentShaderStream */) { - return false; + throw std::runtime_error("Shaders are not supported with OpenGL ES 1"); } //////////////////////////////////////////////////////////// -bool Shader::loadFromStream(InputStream& /* stream */, Type /* type */) -{ - return false; -} +Shader::~Shader() = default; //////////////////////////////////////////////////////////// -bool Shader::loadFromStream(InputStream& /* vertexShaderStream */, InputStream& /* fragmentShaderStream */) -{ - return false; -} +Shader::Shader(Shader&& source) noexcept = default; //////////////////////////////////////////////////////////// -bool Shader::loadFromStream(InputStream& /* vertexShaderStream */, - InputStream& /* geometryShaderStream */, - InputStream& /* fragmentShaderStream */) -{ - return false; -} +Shader& Shader::operator=(Shader&& right) noexcept = default; //////////////////////////////////////////////////////////// -std::optional Shader::createFromFile(const std::filesystem::path& /* filename */, Type /* type */) +bool Shader::loadFromFile(const std::filesystem::path& /* filename */, Type /* type */) { - return std::nullopt; + return false; } //////////////////////////////////////////////////////////// -std::optional Shader::createFromFile(const std::filesystem::path& /* vertexShaderFilename */, - const std::filesystem::path& /* fragmentShaderFilename */) +bool Shader::loadFromFile(const std::filesystem::path& /* vertexShaderFilename */, + const std::filesystem::path& /* fragmentShaderFilename */) { - return std::nullopt; + return false; } //////////////////////////////////////////////////////////// -std::optional Shader::createFromFile(const std::filesystem::path& /* vertexShaderFilename */, - const std::filesystem::path& /* geometryShaderFilename */, - const std::filesystem::path& /* fragmentShaderFilename */) +bool Shader::loadFromFile(const std::filesystem::path& /* vertexShaderFilename */, + const std::filesystem::path& /* geometryShaderFilename */, + const std::filesystem::path& /* fragmentShaderFilename */) { - return std::nullopt; + return false; } //////////////////////////////////////////////////////////// -std::optional Shader::createFromMemory(std::string_view /* shader */, Type /* type */) +bool Shader::loadFromMemory(std::string_view /* shader */, Type /* type */) { - return std::nullopt; + return false; } //////////////////////////////////////////////////////////// -std::optional Shader::createFromMemory(std::string_view /* vertexShader */, std::string_view /* fragmentShader */) +bool Shader::loadFromMemory(std::string_view /* vertexShader */, std::string_view /* fragmentShader */) { - return std::nullopt; + return false; } //////////////////////////////////////////////////////////// -std::optional Shader::createFromMemory(std::string_view /* vertexShader */, - std::string_view /* geometryShader */, - std::string_view /* fragmentShader */) +bool Shader::loadFromMemory(std::string_view /* vertexShader */, + std::string_view /* geometryShader */, + std::string_view /* fragmentShader */) { - return std::nullopt; + return false; } //////////////////////////////////////////////////////////// -std::optional Shader::createFromStream(InputStream& /* stream */, Type /* type */) +bool Shader::loadFromStream(InputStream& /* stream */, Type /* type */) { - return std::nullopt; + return false; } //////////////////////////////////////////////////////////// -std::optional Shader::createFromStream(InputStream& /* vertexShaderStream */, InputStream& /* fragmentShaderStream */) +bool Shader::loadFromStream(InputStream& /* vertexShaderStream */, InputStream& /* fragmentShaderStream */) { - return std::nullopt; + return false; } //////////////////////////////////////////////////////////// -std::optional Shader::createFromStream(InputStream& /* vertexShaderStream */, - InputStream& /* geometryShaderStream */, - InputStream& /* fragmentShaderStream */) +bool Shader::loadFromStream(InputStream& /* vertexShaderStream */, + InputStream& /* geometryShaderStream */, + InputStream& /* fragmentShaderStream */) { - return std::nullopt; + return false; } diff --git a/src/SFML/Graphics/Texture.cpp b/src/SFML/Graphics/Texture.cpp index 45661ae876..1251439704 100644 --- a/src/SFML/Graphics/Texture.cpp +++ b/src/SFML/Graphics/Texture.cpp @@ -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) : GlResource(copy), @@ -361,66 +433,6 @@ bool Texture::loadFromImage(const Image& image, bool sRgb, const IntRect& area) } -//////////////////////////////////////////////////////////// -std::optional Texture::create(Vector2u size, bool sRgb) -{ - auto texture = std::make_optional(); - - if (!texture->resize(size, sRgb)) - return std::nullopt; - - return texture; -} - - -//////////////////////////////////////////////////////////// -std::optional Texture::createFromFile(const std::filesystem::path& filename, bool sRgb, const IntRect& area) -{ - auto texture = std::make_optional(); - - if (!texture->loadFromFile(filename, sRgb, area)) - return std::nullopt; - - return texture; -} - - -//////////////////////////////////////////////////////////// -std::optional Texture::createFromMemory(const void* data, std::size_t size, bool sRgb, const IntRect& area) -{ - auto texture = std::make_optional(); - - if (!texture->loadFromMemory(data, size, sRgb, area)) - return std::nullopt; - - return texture; -} - - -//////////////////////////////////////////////////////////// -std::optional Texture::createFromStream(InputStream& stream, bool sRgb, const IntRect& area) -{ - auto texture = std::make_optional(); - - if (!texture->loadFromStream(stream, sRgb, area)) - return std::nullopt; - - return texture; -} - - -//////////////////////////////////////////////////////////// -std::optional Texture::createFromImage(const Image& image, bool sRgb, const IntRect& area) -{ - auto texture = std::make_optional(); - - if (!texture->loadFromImage(image, sRgb, area)) - return std::nullopt; - - return texture; -} - - //////////////////////////////////////////////////////////// Vector2u Texture::getSize() const { diff --git a/src/SFML/System/FileInputStream.cpp b/src/SFML/System/FileInputStream.cpp index df075a6627..83809cd8f9 100644 --- a/src/SFML/System/FileInputStream.cpp +++ b/src/SFML/System/FileInputStream.cpp @@ -47,6 +47,14 @@ void FileInputStream::FileCloser::operator()(std::FILE* file) 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; @@ -78,18 +86,6 @@ bool FileInputStream::open(const std::filesystem::path& filename) } -//////////////////////////////////////////////////////////// -std::optional FileInputStream::create(const std::filesystem::path& filename) -{ - auto fileInputStream = std::make_optional(); - - if (!fileInputStream->open(filename)) - return std::nullopt; - - return fileInputStream; -} - - //////////////////////////////////////////////////////////// std::optional FileInputStream::read(void* data, std::size_t size) { diff --git a/src/SFML/System/MemoryInputStream.cpp b/src/SFML/System/MemoryInputStream.cpp index 56dec3b4e4..edec0eb5a5 100644 --- a/src/SFML/System/MemoryInputStream.cpp +++ b/src/SFML/System/MemoryInputStream.cpp @@ -35,18 +35,10 @@ namespace sf { //////////////////////////////////////////////////////////// -MemoryInputStream::MemoryInputStream(const void* data, std::size_t sizeInBytes) +MemoryInputStream::MemoryInputStream(const void* data, std::size_t sizeInBytes) : +m_data(static_cast(data)), +m_size(sizeInBytes) { - open(data, sizeInBytes); -} - - -//////////////////////////////////////////////////////////// -void MemoryInputStream::open(const void* data, std::size_t sizeInBytes) -{ - m_data = static_cast(data); - m_size = sizeInBytes; - m_offset = 0; } diff --git a/src/SFML/Window/Cursor.cpp b/src/SFML/Window/Cursor.cpp index 97fd9b30c1..4ced9472d6 100644 --- a/src/SFML/Window/Cursor.cpp +++ b/src/SFML/Window/Cursor.cpp @@ -43,6 +43,25 @@ Cursor::Cursor() : m_impl(std::make_unique()) } +//////////////////////////////////////////////////////////// +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; diff --git a/test/Audio/InputSoundFile.test.cpp b/test/Audio/InputSoundFile.test.cpp index 376c6d3089..ead0e8a501 100644 --- a/test/Audio/InputSoundFile.test.cpp +++ b/test/Audio/InputSoundFile.test.cpp @@ -23,29 +23,27 @@ TEST_CASE("[Audio] sf::InputSoundFile") SECTION("Construction") { - const sf::InputSoundFile inputSoundFile; - CHECK(inputSoundFile.getSampleCount() == 0); - CHECK(inputSoundFile.getChannelCount() == 0); - CHECK(inputSoundFile.getSampleRate() == 0); - CHECK(inputSoundFile.getDuration() == sf::Time::Zero); - CHECK(inputSoundFile.getTimeOffset() == sf::Time::Zero); - CHECK(inputSoundFile.getSampleOffset() == 0); - } - - SECTION("openFromFile()") - { - sf::InputSoundFile inputSoundFile; + SECTION("Default constructor") + { + const sf::InputSoundFile inputSoundFile; + CHECK(inputSoundFile.getSampleCount() == 0); + CHECK(inputSoundFile.getChannelCount() == 0); + CHECK(inputSoundFile.getSampleRate() == 0); + CHECK(inputSoundFile.getDuration() == sf::Time::Zero); + CHECK(inputSoundFile.getTimeOffset() == sf::Time::Zero); + CHECK(inputSoundFile.getSampleOffset() == 0); + } SECTION("Invalid file") { - CHECK(!inputSoundFile.openFromFile("does/not/exist.wav")); + CHECK_THROWS_AS(sf::InputSoundFile("does/not/exist.wav"), std::runtime_error); } SECTION("Valid file") { SECTION("flac") { - REQUIRE(inputSoundFile.openFromFile("Audio/ding.flac")); + const sf::InputSoundFile inputSoundFile("Audio/ding.flac"); CHECK(inputSoundFile.getSampleCount() == 87'798); CHECK(inputSoundFile.getChannelCount() == 1); CHECK(inputSoundFile.getSampleRate() == 44'100); @@ -56,7 +54,7 @@ TEST_CASE("[Audio] sf::InputSoundFile") SECTION("mp3") { - REQUIRE(inputSoundFile.openFromFile("Audio/ding.mp3")); + const sf::InputSoundFile inputSoundFile("Audio/ding.mp3"); CHECK(inputSoundFile.getSampleCount() == 87'798); CHECK(inputSoundFile.getChannelCount() == 1); CHECK(inputSoundFile.getSampleRate() == 44'100); @@ -67,7 +65,7 @@ TEST_CASE("[Audio] sf::InputSoundFile") SECTION("ogg") { - REQUIRE(inputSoundFile.openFromFile("Audio/doodle_pop.ogg")); + const sf::InputSoundFile inputSoundFile("Audio/doodle_pop.ogg"); CHECK(inputSoundFile.getSampleCount() == 2'116'992); CHECK(inputSoundFile.getChannelCount() == 2); CHECK(inputSoundFile.getSampleRate() == 44'100); @@ -78,7 +76,7 @@ TEST_CASE("[Audio] sf::InputSoundFile") SECTION("wav") { - REQUIRE(inputSoundFile.openFromFile("Audio/killdeer.wav")); + const sf::InputSoundFile inputSoundFile("Audio/killdeer.wav"); CHECK(inputSoundFile.getSampleCount() == 112'941); CHECK(inputSoundFile.getChannelCount() == 1); CHECK(inputSoundFile.getSampleRate() == 22'050); @@ -87,37 +85,25 @@ TEST_CASE("[Audio] sf::InputSoundFile") CHECK(inputSoundFile.getSampleOffset() == 0); } } - } - - SECTION("openFromMemory()") - { - const auto memory = loadIntoMemory("Audio/killdeer.wav"); - sf::InputSoundFile inputSoundFile; - REQUIRE(inputSoundFile.openFromMemory(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("openFromStream()") - { - sf::InputSoundFile inputSoundFile; - sf::FileInputStream stream; - - SECTION("Invalid stream") + SECTION("Memory") { - CHECK(!inputSoundFile.openFromStream(stream)); + 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("Valid stream") + SECTION("Stream") { SECTION("flac") { - REQUIRE(stream.open("Audio/ding.flac")); - REQUIRE(inputSoundFile.openFromStream(stream)); + 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); @@ -128,8 +114,8 @@ TEST_CASE("[Audio] sf::InputSoundFile") SECTION("mp3") { - REQUIRE(stream.open("Audio/ding.mp3")); - REQUIRE(inputSoundFile.openFromStream(stream)); + 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); @@ -140,8 +126,8 @@ TEST_CASE("[Audio] sf::InputSoundFile") SECTION("ogg") { - REQUIRE(stream.open("Audio/doodle_pop.ogg")); - REQUIRE(inputSoundFile.openFromStream(stream)); + 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); @@ -152,8 +138,8 @@ TEST_CASE("[Audio] sf::InputSoundFile") SECTION("wav") { - REQUIRE(stream.open("Audio/killdeer.wav")); - REQUIRE(inputSoundFile.openFromStream(stream)); + 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); @@ -164,18 +150,20 @@ TEST_CASE("[Audio] sf::InputSoundFile") } } - SECTION("createFromFile()") + SECTION("openFromFile()") { + sf::InputSoundFile inputSoundFile; + SECTION("Invalid file") { - CHECK(!sf::InputSoundFile::createFromFile("does/not/exist.wav")); + CHECK(!inputSoundFile.openFromFile("does/not/exist.wav")); } SECTION("Valid file") { SECTION("flac") { - const auto inputSoundFile = sf::InputSoundFile::createFromFile("Audio/ding.flac").value(); + REQUIRE(inputSoundFile.openFromFile("Audio/ding.flac")); CHECK(inputSoundFile.getSampleCount() == 87'798); CHECK(inputSoundFile.getChannelCount() == 1); CHECK(inputSoundFile.getSampleRate() == 44'100); @@ -186,7 +174,7 @@ TEST_CASE("[Audio] sf::InputSoundFile") SECTION("mp3") { - const auto inputSoundFile = sf::InputSoundFile::createFromFile("Audio/ding.mp3").value(); + REQUIRE(inputSoundFile.openFromFile("Audio/ding.mp3")); CHECK(inputSoundFile.getSampleCount() == 87'798); CHECK(inputSoundFile.getChannelCount() == 1); CHECK(inputSoundFile.getSampleRate() == 44'100); @@ -197,7 +185,7 @@ TEST_CASE("[Audio] sf::InputSoundFile") SECTION("ogg") { - const auto inputSoundFile = sf::InputSoundFile::createFromFile("Audio/doodle_pop.ogg").value(); + REQUIRE(inputSoundFile.openFromFile("Audio/doodle_pop.ogg")); CHECK(inputSoundFile.getSampleCount() == 2'116'992); CHECK(inputSoundFile.getChannelCount() == 2); CHECK(inputSoundFile.getSampleRate() == 44'100); @@ -208,7 +196,7 @@ TEST_CASE("[Audio] sf::InputSoundFile") SECTION("wav") { - const auto inputSoundFile = sf::InputSoundFile::createFromFile("Audio/killdeer.wav").value(); + REQUIRE(inputSoundFile.openFromFile("Audio/killdeer.wav")); CHECK(inputSoundFile.getSampleCount() == 112'941); CHECK(inputSoundFile.getChannelCount() == 1); CHECK(inputSoundFile.getSampleRate() == 22'050); @@ -219,10 +207,11 @@ TEST_CASE("[Audio] sf::InputSoundFile") } } - SECTION("createFromMemory()") + SECTION("openFromMemory()") { - const auto memory = loadIntoMemory("Audio/killdeer.wav"); - const auto inputSoundFile = sf::InputSoundFile::createFromMemory(memory.data(), memory.size()).value(); + const auto memory = loadIntoMemory("Audio/killdeer.wav"); + sf::InputSoundFile inputSoundFile; + REQUIRE(inputSoundFile.openFromMemory(memory.data(), memory.size())); CHECK(inputSoundFile.getSampleCount() == 112'941); CHECK(inputSoundFile.getChannelCount() == 1); CHECK(inputSoundFile.getSampleRate() == 22'050); @@ -231,54 +220,65 @@ TEST_CASE("[Audio] sf::InputSoundFile") CHECK(inputSoundFile.getSampleOffset() == 0); } - SECTION("createFromStream()") + SECTION("openFromStream()") { - 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); - } + sf::InputSoundFile inputSoundFile; + sf::FileInputStream stream; - SECTION("mp3") + SECTION("Invalid stream") { - 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); + CHECK(!inputSoundFile.openFromStream(stream)); } - SECTION("ogg") + SECTION("Valid stream") { - 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("flac") + { + REQUIRE(stream.open("Audio/ding.flac")); + REQUIRE(inputSoundFile.openFromStream(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("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("mp3") + { + REQUIRE(stream.open("Audio/ding.mp3")); + REQUIRE(inputSoundFile.openFromStream(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") + { + REQUIRE(stream.open("Audio/doodle_pop.ogg")); + REQUIRE(inputSoundFile.openFromStream(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") + { + REQUIRE(stream.open("Audio/killdeer.wav")); + REQUIRE(inputSoundFile.openFromStream(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); + } } } @@ -286,7 +286,7 @@ TEST_CASE("[Audio] sf::InputSoundFile") { SECTION("flac") { - auto inputSoundFile = sf::InputSoundFile::createFromFile("Audio/ding.flac").value(); + sf::InputSoundFile inputSoundFile("Audio/ding.flac"); inputSoundFile.seek(1'000); CHECK(inputSoundFile.getTimeOffset() == sf::microseconds(22'675)); CHECK(inputSoundFile.getSampleOffset() == 1'000); @@ -294,7 +294,7 @@ TEST_CASE("[Audio] sf::InputSoundFile") SECTION("mp3") { - auto inputSoundFile = sf::InputSoundFile::createFromFile("Audio/ding.mp3").value(); + sf::InputSoundFile inputSoundFile("Audio/ding.mp3"); inputSoundFile.seek(1'000); CHECK(inputSoundFile.getTimeOffset() == sf::microseconds(22'675)); CHECK(inputSoundFile.getSampleOffset() == 1'000); @@ -302,7 +302,7 @@ TEST_CASE("[Audio] sf::InputSoundFile") SECTION("ogg") { - auto inputSoundFile = sf::InputSoundFile::createFromFile("Audio/doodle_pop.ogg").value(); + sf::InputSoundFile inputSoundFile("Audio/doodle_pop.ogg"); inputSoundFile.seek(1'000); CHECK(inputSoundFile.getTimeOffset() == sf::microseconds(11'337)); CHECK(inputSoundFile.getSampleOffset() == 1'000); @@ -310,7 +310,7 @@ TEST_CASE("[Audio] sf::InputSoundFile") SECTION("wav") { - auto inputSoundFile = sf::InputSoundFile::createFromFile("Audio/killdeer.wav").value(); + sf::InputSoundFile inputSoundFile("Audio/killdeer.wav"); inputSoundFile.seek(1'000); CHECK(inputSoundFile.getTimeOffset() == sf::microseconds(45'351)); CHECK(inputSoundFile.getSampleOffset() == 1'000); @@ -319,7 +319,7 @@ TEST_CASE("[Audio] sf::InputSoundFile") SECTION("seek(Time)") { - auto inputSoundFile = sf::InputSoundFile::createFromFile("Audio/ding.flac").value(); + sf::InputSoundFile inputSoundFile("Audio/ding.flac"); inputSoundFile.seek(sf::milliseconds(100)); CHECK(inputSoundFile.getSampleCount() == 87'798); CHECK(inputSoundFile.getChannelCount() == 1); @@ -331,7 +331,7 @@ TEST_CASE("[Audio] sf::InputSoundFile") SECTION("read()") { - auto inputSoundFile = sf::InputSoundFile::createFromFile("Audio/ding.flac").value(); + sf::InputSoundFile inputSoundFile("Audio/ding.flac"); SECTION("Null address") { @@ -349,7 +349,7 @@ TEST_CASE("[Audio] sf::InputSoundFile") { 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(samples == std::array{0, 1, -1, 4}); CHECK(inputSoundFile.read(samples.data(), samples.size()) == 4); @@ -358,7 +358,7 @@ TEST_CASE("[Audio] sf::InputSoundFile") 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(samples == std::array{0, -2, 0, 2}); CHECK(inputSoundFile.read(samples.data(), samples.size()) == 4); @@ -367,7 +367,7 @@ TEST_CASE("[Audio] sf::InputSoundFile") 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(samples == std::array{-827, -985, -1168, -1319}); CHECK(inputSoundFile.read(samples.data(), samples.size()) == 4); @@ -383,7 +383,7 @@ TEST_CASE("[Audio] sf::InputSoundFile") SECTION("close()") { - auto inputSoundFile = sf::InputSoundFile::createFromFile("Audio/ding.flac").value(); + sf::InputSoundFile inputSoundFile("Audio/ding.flac"); inputSoundFile.close(); CHECK(inputSoundFile.getSampleCount() == 0); CHECK(inputSoundFile.getChannelCount() == 0); diff --git a/test/Audio/Music.test.cpp b/test/Audio/Music.test.cpp index 5d7aa38c7c..fede6b645e 100644 --- a/test/Audio/Music.test.cpp +++ b/test/Audio/Music.test.cpp @@ -32,18 +32,84 @@ TEST_CASE("[Audio] sf::Music", runAudioDeviceTests()) CHECK(timeSpan.length == sf::Time::Zero); } - SECTION("Construction") + SECTION("Constructor") { - const sf::Music music; - CHECK(music.getDuration() == sf::Time::Zero); - const auto [offset, length] = music.getLoopPoints(); - CHECK(offset == sf::Time::Zero); - CHECK(length == sf::Time::Zero); - CHECK(music.getChannelCount() == 0); - CHECK(music.getSampleRate() == 0); - CHECK(music.getStatus() == sf::Music::Status::Stopped); - CHECK(music.getPlayingOffset() == sf::Time::Zero); - CHECK(!music.getLoop()); + SECTION("Default constructor") + { + const sf::Music music; + CHECK(music.getDuration() == sf::Time::Zero); + const auto [offset, length] = music.getLoopPoints(); + CHECK(offset == sf::Time::Zero); + CHECK(length == sf::Time::Zero); + CHECK(music.getChannelCount() == 0); + CHECK(music.getSampleRate() == 0); + 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 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()") @@ -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 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") { - auto music = sf::Music::createFromFile("Audio/ding.mp3").value(); + sf::Music music("Audio/ding.mp3"); // Wait for background thread to start music.play(); @@ -237,7 +240,7 @@ TEST_CASE("[Audio] sf::Music", runAudioDeviceTests()) 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)}); const auto [offset, length] = music.getLoopPoints(); CHECK(offset == sf::seconds(1)); diff --git a/test/Audio/OutputSoundFile.test.cpp b/test/Audio/OutputSoundFile.test.cpp index 765e79ddd0..b1aee5d5fc 100644 --- a/test/Audio/OutputSoundFile.test.cpp +++ b/test/Audio/OutputSoundFile.test.cpp @@ -2,6 +2,7 @@ #include +static_assert(std::is_default_constructible_v); static_assert(!std::is_copy_constructible_v); static_assert(!std::is_copy_assignable_v); static_assert(std::is_nothrow_move_constructible_v); diff --git a/test/Audio/Sound.test.cpp b/test/Audio/Sound.test.cpp index 70717f0c59..1b156c2a8e 100644 --- a/test/Audio/Sound.test.cpp +++ b/test/Audio/Sound.test.cpp @@ -26,7 +26,7 @@ TEST_CASE("[Audio] sf::Sound", runAudioDeviceTests()) STATIC_CHECK(std::has_virtual_destructor_v); } - const auto soundBuffer = sf::SoundBuffer::createFromFile("Audio/ding.flac").value(); + const sf::SoundBuffer soundBuffer("Audio/ding.flac"); SECTION("Construction") { @@ -52,7 +52,7 @@ TEST_CASE("[Audio] sf::Sound", runAudioDeviceTests()) SECTION("Assignment") { - const sf::SoundBuffer otherSoundBuffer = sf::SoundBuffer::createFromFile("Audio/ding.flac").value(); + const sf::SoundBuffer otherSoundBuffer("Audio/ding.flac"); sf::Sound soundCopy(otherSoundBuffer); soundCopy = sound; CHECK(&soundCopy.getBuffer() == &soundBuffer); @@ -64,7 +64,7 @@ TEST_CASE("[Audio] sf::Sound", runAudioDeviceTests()) 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); sound.setBuffer(otherSoundBuffer); CHECK(&sound.getBuffer() == &otherSoundBuffer); diff --git a/test/Audio/SoundBuffer.test.cpp b/test/Audio/SoundBuffer.test.cpp index 94cb0c9717..aae378ebff 100644 --- a/test/Audio/SoundBuffer.test.cpp +++ b/test/Audio/SoundBuffer.test.cpp @@ -24,17 +24,69 @@ TEST_CASE("[Audio] sf::SoundBuffer", runAudioDeviceTests()) SECTION("Construction") { - const sf::SoundBuffer soundBuffer; - CHECK(soundBuffer.getSamples() == nullptr); - CHECK(soundBuffer.getSampleCount() == 0); - CHECK(soundBuffer.getSampleRate() == 44100); - CHECK(soundBuffer.getChannelCount() == 1); - CHECK(soundBuffer.getDuration() == sf::Time::Zero); + SECTION("Default constructor") + { + const sf::SoundBuffer soundBuffer; + CHECK(soundBuffer.getSamples() == nullptr); + CHECK(soundBuffer.getSampleCount() == 0); + 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 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") { - const auto soundBuffer = sf::SoundBuffer::createFromFile("Audio/ding.flac").value(); + const sf::SoundBuffer soundBuffer("Audio/ding.flac"); SECTION("Construction") { @@ -48,8 +100,8 @@ TEST_CASE("[Audio] sf::SoundBuffer", runAudioDeviceTests()) SECTION("Assignment") { - sf::SoundBuffer soundBufferCopy = sf::SoundBuffer::createFromFile("Audio/doodle_pop.ogg").value(); - soundBufferCopy = soundBuffer; + sf::SoundBuffer soundBufferCopy("Audio/doodle_pop.ogg"); + soundBufferCopy = soundBuffer; CHECK(soundBufferCopy.getSamples() != nullptr); CHECK(soundBufferCopy.getSampleCount() == 87798); 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 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()") { 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)); } - const auto soundBuffer = sf::SoundBuffer::createFromFile(filename).value(); + const sf::SoundBuffer soundBuffer(filename); CHECK(soundBuffer.getSamples() != nullptr); CHECK(soundBuffer.getSampleCount() == 87798); CHECK(soundBuffer.getSampleRate() == 44100); diff --git a/test/Audio/SoundFileFactory.test.cpp b/test/Audio/SoundFileFactory.test.cpp index 2b8d6e0a22..5d797657cb 100644 --- a/test/Audio/SoundFileFactory.test.cpp +++ b/test/Audio/SoundFileFactory.test.cpp @@ -11,7 +11,6 @@ #include #include -#include #include #include @@ -110,30 +109,29 @@ TEST_CASE("[Audio] sf::SoundFileFactory") SECTION("createReaderFromStream()") { - std::optional stream; + sf::FileInputStream stream; SECTION("flac") { - stream = sf::FileInputStream::create("Audio/ding.flac"); + REQUIRE(stream.open("Audio/ding.flac")); } SECTION("mp3") { - stream = sf::FileInputStream::create("Audio/ding.mp3"); + REQUIRE(stream.open("Audio/ding.mp3")); } SECTION("ogg") { - stream = sf::FileInputStream::create("Audio/doodle_pop.ogg"); + REQUIRE(stream.open("Audio/doodle_pop.ogg")); } 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()") diff --git a/test/Graphics/Drawable.test.cpp b/test/Graphics/Drawable.test.cpp index 3dafc19ca5..4b9521995a 100644 --- a/test/Graphics/Drawable.test.cpp +++ b/test/Graphics/Drawable.test.cpp @@ -46,7 +46,7 @@ TEST_CASE("[Graphics] sf::Drawable", runDisplayTests()) SECTION("draw()") { const DrawableTest drawableTest; - auto renderTexture = sf::RenderTexture::create({32, 32}).value(); + sf::RenderTexture renderTexture({32, 32}); CHECK(drawableTest.callCount() == 0); renderTexture.draw(drawableTest); CHECK(drawableTest.callCount() == 1); diff --git a/test/Graphics/Font.test.cpp b/test/Graphics/Font.test.cpp index 2f017abc52..fef5e7163c 100644 --- a/test/Graphics/Font.test.cpp +++ b/test/Graphics/Font.test.cpp @@ -23,66 +23,92 @@ TEST_CASE("[Graphics] sf::Font", runDisplayTests()) SECTION("Construction") { - const sf::Font font; - CHECK(font.getInfo().family.empty()); - CHECK(!font.hasGlyph(0)); - CHECK(font.getLineSpacing(0) == 0); - CHECK(font.getUnderlinePosition(0) == 0); - CHECK(font.getUnderlineThickness(0) == 0); - CHECK(font.isSmooth()); - } - - SECTION("openFromFile()") - { - sf::Font font; - - SECTION("Invalid filename") + SECTION("Default constructor") { - CHECK(!font.openFromFile("does/not/exist.ttf")); + const sf::Font font; + CHECK(font.getInfo().family.empty()); + CHECK(!font.hasGlyph(0)); + CHECK(font.getLineSpacing(0) == 0); + CHECK(font.getUnderlinePosition(0) == 0); + CHECK(font.getUnderlineThickness(0) == 0); + CHECK(font.isSmooth()); } - SECTION("Successful load") + SECTION("File") { - REQUIRE(font.openFromFile("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("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("openFromMemory()") - { - sf::Font font; - SECTION("Invalid data and size") + SECTION("Memory") { - CHECK(!font.openFromMemory(nullptr, 1)); - const std::byte testByte{0xCD}; - CHECK(!font.openFromMemory(&testByte, 0)); + 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("Successful load") + SECTION("Stream") { - const auto memory = loadIntoMemory("Graphics/tuffy.ttf"); - REQUIRE(font.openFromMemory(memory.data(), memory.size())); + 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); @@ -107,20 +133,18 @@ TEST_CASE("[Graphics] sf::Font", runDisplayTests()) } } - SECTION("openFromStream()") + SECTION("openFromFile()") { - sf::Font font; - sf::FileInputStream stream; + sf::Font font; - SECTION("Invalid stream") + SECTION("Invalid filename") { - CHECK(!font.openFromStream(stream)); + CHECK(!font.openFromFile("does/not/exist.ttf")); } SECTION("Successful load") { - REQUIRE(stream.open("Graphics/tuffy.ttf")); - REQUIRE(font.openFromStream(stream)); + REQUIRE(font.openFromFile("Graphics/tuffy.ttf")); CHECK(font.getInfo().family == "Tuffy"); const auto& glyph = font.getGlyph(0x45, 16, false); CHECK(glyph.advance == 9); @@ -145,16 +169,21 @@ TEST_CASE("[Graphics] sf::Font", runDisplayTests()) } } - SECTION("createFromFile()") + SECTION("openFromMemory()") { - SECTION("Invalid filename") + sf::Font font; + + SECTION("Invalid data and size") { - CHECK(!sf::Font::createFromFile("does/not/exist.ttf")); + CHECK(!font.openFromMemory(nullptr, 1)); + const std::byte testByte{0xCD}; + CHECK(!font.openFromMemory(&testByte, 0)); } - SECTION("Valid file") + SECTION("Successful load") { - const auto font = sf::Font::createFromFile("Graphics/tuffy.ttf").value(); + const auto memory = loadIntoMemory("Graphics/tuffy.ttf"); + REQUIRE(font.openFromMemory(memory.data(), memory.size())); CHECK(font.getInfo().family == "Tuffy"); const auto& glyph = font.getGlyph(0x45, 16, false); CHECK(glyph.advance == 9); @@ -179,19 +208,20 @@ TEST_CASE("[Graphics] sf::Font", runDisplayTests()) } } - SECTION("createFromMemory()") + SECTION("openFromStream()") { - SECTION("Invalid data and size") + sf::Font font; + sf::FileInputStream stream; + + SECTION("Invalid stream") { - CHECK(!sf::Font::createFromMemory(nullptr, 1)); - const std::byte testByte{0xCD}; - CHECK(!sf::Font::createFromMemory(&testByte, 0)); + CHECK(!font.openFromStream(stream)); } - SECTION("Valid data") + SECTION("Successful load") { - const auto memory = loadIntoMemory("Graphics/tuffy.ttf"); - const auto font = sf::Font::createFromMemory(memory.data(), memory.size()).value(); + REQUIRE(stream.open("Graphics/tuffy.ttf")); + REQUIRE(font.openFromStream(stream)); CHECK(font.getInfo().family == "Tuffy"); const auto& glyph = font.getGlyph(0x45, 16, false); CHECK(glyph.advance == 9); @@ -216,36 +246,9 @@ TEST_CASE("[Graphics] sf::Font", runDisplayTests()) } } - 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") { - auto font = sf::Font::createFromFile("Graphics/tuffy.ttf").value(); + sf::Font font("Graphics/tuffy.ttf"); font.setSmooth(false); CHECK(!font.isSmooth()); } diff --git a/test/Graphics/Image.test.cpp b/test/Graphics/Image.test.cpp index 851e7ab2dd..f4857716dd 100644 --- a/test/Graphics/Image.test.cpp +++ b/test/Graphics/Image.test.cpp @@ -19,15 +19,123 @@ TEST_CASE("[Graphics] sf::Image") STATIC_CHECK(std::is_nothrow_move_assignable_v); } - SECTION("Default constructor") - { - const sf::Image image; - CHECK(image.getSize() == sf::Vector2u()); - CHECK(image.getPixelsPtr() == nullptr); - } - 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 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") { 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 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 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("Invalid size") @@ -426,7 +426,7 @@ TEST_CASE("[Graphics] sf::Image") // 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.getPixelsPtr() != nullptr); diff --git a/test/Graphics/Render.test.cpp b/test/Graphics/Render.test.cpp index 28c9da10c8..c01bf6860f 100644 --- a/test/Graphics/Render.test.cpp +++ b/test/Graphics/Render.test.cpp @@ -12,9 +12,7 @@ TEST_CASE("[Graphics] Render Tests", runDisplayTests()) { SECTION("Stencil Tests") { - auto renderTexture = sf::RenderTexture::create({100, 100}, sf::ContextSettings{0 /* depthBits */, 8 /* stencilBits */}) - .value(); - + sf::RenderTexture renderTexture({100, 100}, sf::ContextSettings{0 /* depthBits */, 8 /* stencilBits */}); renderTexture.clear(sf::Color::Red, 127); sf::RectangleShape shape1({100, 100}); diff --git a/test/Graphics/RenderTexture.test.cpp b/test/Graphics/RenderTexture.test.cpp index bb2d718f61..c351c182e0 100644 --- a/test/Graphics/RenderTexture.test.cpp +++ b/test/Graphics/RenderTexture.test.cpp @@ -17,20 +17,45 @@ TEST_CASE("[Graphics] sf::RenderTexture", runDisplayTests()) SECTION("Construction") { - const sf::RenderTexture renderTexture; - CHECK(!renderTexture.isSmooth()); - CHECK(!renderTexture.isRepeated()); - CHECK(renderTexture.getSize() == sf::Vector2u(0, 0)); + SECTION("Default constructor") + { + const sf::RenderTexture renderTexture; + 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(sf::RenderTexture::create({100, 100}, sf::ContextSettings{0 /* depthBits */, 8 /* stencilBits */})); + CHECK(renderTexture.resize({100, 100}, sf::ContextSettings{8 /* depthBits */, 0 /* 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.isSmooth()); CHECK(!renderTexture.isRepeated()); @@ -66,27 +91,27 @@ TEST_CASE("[Graphics] sf::RenderTexture", runDisplayTests()) SECTION("Set/get smooth") { - auto renderTexture = sf::RenderTexture::create({64, 64}).value(); + sf::RenderTexture renderTexture({64, 64}); renderTexture.setSmooth(true); CHECK(renderTexture.isSmooth()); } SECTION("Set/get repeated") { - auto renderTexture = sf::RenderTexture::create({64, 64}).value(); + sf::RenderTexture renderTexture({64, 64}); renderTexture.setRepeated(true); CHECK(renderTexture.isRepeated()); } SECTION("generateMipmap()") { - auto renderTexture = sf::RenderTexture::create({64, 64}).value(); + sf::RenderTexture renderTexture({64, 64}); CHECK(renderTexture.generateMipmap()); } SECTION("setActive()") { - auto renderTexture = sf::RenderTexture::create({64, 64}).value(); + sf::RenderTexture renderTexture({64, 64}); CHECK(renderTexture.setActive()); CHECK(renderTexture.setActive(false)); CHECK(renderTexture.setActive(true)); @@ -94,7 +119,7 @@ TEST_CASE("[Graphics] sf::RenderTexture", runDisplayTests()) 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)); } } diff --git a/test/Graphics/RenderWindow.test.cpp b/test/Graphics/RenderWindow.test.cpp index d1cde4b71d..e2ccbff8b4 100644 --- a/test/Graphics/RenderWindow.test.cpp +++ b/test/Graphics/RenderWindow.test.cpp @@ -75,7 +75,7 @@ TEST_CASE("[Graphics] sf::RenderWindow", runDisplayTests()) sf::ContextSettings{}); 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); texture.update(window); diff --git a/test/Graphics/Shader.test.cpp b/test/Graphics/Shader.test.cpp index 6405fd78e6..5de640e734 100644 --- a/test/Graphics/Shader.test.cpp +++ b/test/Graphics/Shader.test.cpp @@ -145,6 +145,18 @@ TEST_CASE("[Graphics] sf::Shader (Dummy Implementation)", skipShaderDummyTests() 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()") { 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, 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()) @@ -177,8 +180,181 @@ TEST_CASE("[Graphics] sf::Shader", skipShaderFullTests()) SECTION("Construction") { - const sf::Shader shader; - CHECK(shader.getNativeHandle() == 0); + SECTION("Default constructor") + { + 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") @@ -203,16 +379,16 @@ TEST_CASE("[Graphics] sf::Shader", skipShaderFullTests()) { 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); CHECK(shader.getNativeHandle() != 0); } SECTION("Assignment") { - sf::Shader movedShader = sf::Shader::createFromFile("Graphics/shader.vert", sf::Shader::Type::Vertex).value(); - sf::Shader shader = sf::Shader::createFromFile("Graphics/shader.frag", sf::Shader::Type::Fragment).value(); - shader = std::move(movedShader); + sf::Shader movedShader(std::filesystem::path("Graphics/shader.vert"), sf::Shader::Type::Vertex); + sf::Shader shader(std::filesystem::path("Graphics/shader.frag"), sf::Shader::Type::Fragment); + shader = std::move(movedShader); CHECK(shader.getNativeHandle() != 0); } } @@ -255,7 +431,7 @@ TEST_CASE("[Graphics] sf::Shader", skipShaderFullTests()) { sf::Shader shader; 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(vertexSource, fragmentSource) == sf::Shader::isAvailable()); CHECK(shader.loadFromMemory(vertexSource, geometrySource, fragmentSource) == sf::Shader::isGeometryAvailable()); @@ -300,100 +476,4 @@ TEST_CASE("[Graphics] sf::Shader", skipShaderFullTests()) CHECK(static_cast(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(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(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(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(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(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(shader->getNativeHandle()) == sf::Shader::isGeometryAvailable()); - } - } } diff --git a/test/Graphics/Shape.test.cpp b/test/Graphics/Shape.test.cpp index 1b577df8f4..6a63991830 100644 --- a/test/Graphics/Shape.test.cpp +++ b/test/Graphics/Shape.test.cpp @@ -66,8 +66,8 @@ TEST_CASE("[Graphics] sf::Shape", runDisplayTests()) SECTION("Set/get texture") { - const auto texture = sf::Texture::create({64, 64}).value(); - TriangleShape triangleShape({}); + const sf::Texture texture(sf::Vector2u(64, 64)); + TriangleShape triangleShape({}); triangleShape.setTexture(&texture, true); CHECK(triangleShape.getTexture() == &texture); } diff --git a/test/Graphics/Sprite.test.cpp b/test/Graphics/Sprite.test.cpp index 9d71b6ecdc..bcde531106 100644 --- a/test/Graphics/Sprite.test.cpp +++ b/test/Graphics/Sprite.test.cpp @@ -22,7 +22,7 @@ TEST_CASE("[Graphics] sf::Sprite", runDisplayTests()) STATIC_CHECK(std::is_nothrow_move_assignable_v); } - const auto texture = sf::Texture::create({64, 64}).value(); + const sf::Texture texture(sf::Vector2u(64, 64)); SECTION("Construction") { @@ -60,7 +60,7 @@ TEST_CASE("[Graphics] sf::Sprite", runDisplayTests()) SECTION("Set/get 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); CHECK(&sprite.getTexture() == &otherTexture); } diff --git a/test/Graphics/Text.test.cpp b/test/Graphics/Text.test.cpp index c926c382ce..ab1a383895 100644 --- a/test/Graphics/Text.test.cpp +++ b/test/Graphics/Text.test.cpp @@ -21,7 +21,7 @@ TEST_CASE("[Graphics] sf::Text", runDisplayTests()) STATIC_CHECK(std::is_nothrow_move_assignable_v); } - const auto font = sf::Font::createFromFile("Graphics/tuffy.ttf").value(); + const sf::Font font("Graphics/tuffy.ttf"); SECTION("Construction") { @@ -86,8 +86,8 @@ TEST_CASE("[Graphics] sf::Text", runDisplayTests()) SECTION("Set/get font") { - sf::Text text(font); - const auto otherFont = sf::Font::createFromFile("Graphics/tuffy.ttf").value(); + sf::Text text(font); + const sf::Font otherFont("Graphics/tuffy.ttf"); text.setFont(otherFont); CHECK(&text.getFont() == &otherFont); } diff --git a/test/Graphics/Texture.test.cpp b/test/Graphics/Texture.test.cpp index b4303329c4..398bbf88b1 100644 --- a/test/Graphics/Texture.test.cpp +++ b/test/Graphics/Texture.test.cpp @@ -24,12 +24,99 @@ TEST_CASE("[Graphics] sf::Texture", runDisplayTests()) SECTION("Construction") { - const sf::Texture texture; - CHECK(texture.getSize() == sf::Vector2u()); - CHECK(!texture.isSmooth()); - CHECK(!texture.isSrgb()); - CHECK(!texture.isRepeated()); - CHECK(texture.getNativeHandle() == 0); + SECTION("Default constructor") + { + const sf::Texture texture; + CHECK(texture.getSize() == sf::Vector2u()); + CHECK(!texture.isSmooth()); + 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") @@ -58,12 +145,12 @@ TEST_CASE("[Graphics] sf::Texture", runDisplayTests()) } } - SECTION("Move semantics (create)") + SECTION("Move semantics") { SECTION("Construction") { - sf::Texture movedTexture = sf::Texture::create({64, 64}).value(); - const sf::Texture texture = std::move(movedTexture); + sf::Texture movedTexture(sf::Vector2u(64, 64)); + const sf::Texture texture = std::move(movedTexture); CHECK(texture.getSize() == sf::Vector2u(64, 64)); CHECK(!texture.isSmooth()); CHECK(!texture.isSrgb()); @@ -73,9 +160,9 @@ TEST_CASE("[Graphics] sf::Texture", runDisplayTests()) SECTION("Assignment") { - sf::Texture movedTexture = sf::Texture::create({64, 64}).value(); - sf::Texture texture = sf::Texture::create({128, 128}).value(); - texture = std::move(movedTexture); + sf::Texture movedTexture(sf::Vector2u(64, 64)); + sf::Texture texture(sf::Vector2u(128, 128)); + texture = std::move(movedTexture); CHECK(texture.getSize() == sf::Vector2u(64, 64)); CHECK(!texture.isSmooth()); 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()") { 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") { 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); SECTION("Construction") @@ -283,8 +286,8 @@ TEST_CASE("[Graphics] sf::Texture", runDisplayTests()) SECTION("Assignment") { - sf::Texture textureCopy = sf::Texture::create({64, 64}).value(); - textureCopy = texture; + sf::Texture textureCopy(sf::Vector2u(64, 64)); + textureCopy = texture; REQUIRE(textureCopy.getSize() == sf::Vector2u(1, 2)); CHECK(textureCopy.copyToImage().getPixel(sf::Vector2u(0, 1)) == sf::Color::Red); } @@ -297,14 +300,14 @@ TEST_CASE("[Graphics] sf::Texture", runDisplayTests()) SECTION("Pixels") { - auto texture = sf::Texture::create(sf::Vector2u(1, 1)).value(); + sf::Texture texture(sf::Vector2u(1, 1)); texture.update(yellow); CHECK(texture.copyToImage().getPixel(sf::Vector2u(0, 0)) == sf::Color::Yellow); } 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(cyan, sf::Vector2u(1, 1), sf::Vector2u(1, 0)); CHECK(texture.copyToImage().getPixel(sf::Vector2u(0, 0)) == sf::Color::Yellow); @@ -313,19 +316,19 @@ TEST_CASE("[Graphics] sf::Texture", runDisplayTests()) SECTION("Another texture") { - auto otherTexture = sf::Texture::create(sf::Vector2u(1, 1)).value(); + sf::Texture otherTexture(sf::Vector2u(1, 1)); otherTexture.update(cyan); - auto texture = sf::Texture::create(sf::Vector2u(1, 1)).value(); + sf::Texture texture(sf::Vector2u(1, 1)); texture.update(otherTexture); CHECK(texture.copyToImage().getPixel(sf::Vector2u(0, 0)) == sf::Color::Cyan); } SECTION("Another texture and destination") { - auto texture = sf::Texture::create(sf::Vector2u(2, 1)).value(); - auto otherTexture1 = sf::Texture::create(sf::Vector2u(1, 1)).value(); + sf::Texture texture(sf::Vector2u(2, 1)); + sf::Texture otherTexture1(sf::Vector2u(1, 1)); otherTexture1.update(cyan); - auto otherTexture2 = sf::Texture::create(sf::Vector2u(1, 1)).value(); + sf::Texture otherTexture2(sf::Vector2u(1, 1)); otherTexture2.update(yellow); texture.update(otherTexture1, sf::Vector2u(0, 0)); texture.update(otherTexture2, sf::Vector2u(1, 0)); @@ -335,7 +338,7 @@ TEST_CASE("[Graphics] sf::Texture", runDisplayTests()) 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); texture.update(image); 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") { - 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); texture.update(image1); 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") { - sf::Texture texture = sf::Texture::create({64, 64}).value(); + sf::Texture texture(sf::Vector2u(64, 64)); CHECK(!texture.isSmooth()); texture.setSmooth(true); CHECK(texture.isSmooth()); @@ -366,7 +369,7 @@ TEST_CASE("[Graphics] sf::Texture", runDisplayTests()) SECTION("Set/get repeated") { - sf::Texture texture = sf::Texture::create({64, 64}).value(); + sf::Texture texture(sf::Vector2u(64, 64)); CHECK(!texture.isRepeated()); texture.setRepeated(true); CHECK(texture.isRepeated()); @@ -376,7 +379,7 @@ TEST_CASE("[Graphics] sf::Texture", runDisplayTests()) SECTION("generateMipmap()") { - sf::Texture texture = sf::Texture::create({100, 100}).value(); + sf::Texture texture(sf::Vector2u(100, 100)); 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 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.setSmooth(false); 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.setSmooth(true); texture2.setRepeated(false); diff --git a/test/System/FileInputStream.test.cpp b/test/System/FileInputStream.test.cpp index 777082ccb1..dd0b2c864c 100644 --- a/test/System/FileInputStream.test.cpp +++ b/test/System/FileInputStream.test.cpp @@ -72,24 +72,38 @@ TEST_CASE("[System] sf::FileInputStream") STATIC_CHECK(std::is_nothrow_move_assignable_v); } - 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"); 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 constructor") { - auto movedFileInputStream = sf::FileInputStream::create(temporaryFile.getPath()).value(); - sf::FileInputStream fileInputStream = std::move(movedFileInputStream); + sf::FileInputStream movedFileInputStream(temporaryFile.getPath()); + sf::FileInputStream fileInputStream = std::move(movedFileInputStream); CHECK(fileInputStream.read(buffer, 6) == 6); CHECK(fileInputStream.tell() == 6); CHECK(fileInputStream.getSize() == 11); @@ -98,10 +112,10 @@ TEST_CASE("[System] sf::FileInputStream") SECTION("Move assignment") { - auto movedFileInputStream = sf::FileInputStream::create(temporaryFile.getPath()).value(); + sf::FileInputStream movedFileInputStream(temporaryFile.getPath()); const TemporaryFile temporaryFile2("Hello world the sequel"); - auto fileInputStream = sf::FileInputStream::create(temporaryFile2.getPath()).value(); - fileInputStream = std::move(movedFileInputStream); + sf::FileInputStream fileInputStream(temporaryFile2.getPath()); + fileInputStream = std::move(movedFileInputStream); CHECK(fileInputStream.read(buffer, 6) == 6); CHECK(fileInputStream.tell() == 6); CHECK(fileInputStream.getSize() == 11); @@ -123,7 +137,7 @@ TEST_CASE("[System] sf::FileInputStream") 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.tell() == 5); CHECK(fileInputStream.getSize() == 11); diff --git a/test/System/MemoryInputStream.test.cpp b/test/System/MemoryInputStream.test.cpp index e8ef667990..0beb47d46f 100644 --- a/test/System/MemoryInputStream.test.cpp +++ b/test/System/MemoryInputStream.test.cpp @@ -18,8 +18,17 @@ TEST_CASE("[System] sf::MemoryInputStream") 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; SECTION("Zero length") diff --git a/test/Window/Cursor.test.cpp b/test/Window/Cursor.test.cpp index f41e54a845..79bff581e3 100644 --- a/test/Window/Cursor.test.cpp +++ b/test/Window/Cursor.test.cpp @@ -17,6 +17,37 @@ TEST_CASE("[Window] sf::Cursor", runDisplayTests()) STATIC_CHECK(std::is_nothrow_move_assignable_v); } + SECTION("Constructor") + { + SECTION("Pixels") + { + static constexpr std::array 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()") { static constexpr std::array pixels{}; diff --git a/tools/xcode/templates/SFML/SFML App.xctemplate/main.cpp b/tools/xcode/templates/SFML/SFML App.xctemplate/main.cpp index dac6a84dbe..f9ea74b82a 100644 --- a/tools/xcode/templates/SFML/SFML App.xctemplate/main.cpp +++ b/tools/xcode/templates/SFML/SFML App.xctemplate/main.cpp @@ -26,16 +26,16 @@ int main() sf::RenderWindow window(sf::VideoMode({800, 600}), "SFML window"); // Set the Icon - const auto icon = sf::Image::loadFromFile(resourcePath() / "icon.png").value(); + const sf::Image icon(resourcePath() / "icon.png"); window.setIcon(icon); // Load a sprite to display - const auto texture = sf::Texture::loadFromFile(resourcePath() / "background.jpg").value(); - sf::Sprite sprite(texture); + const sf::Texture texture(resourcePath() / "background.jpg"); + sf::Sprite sprite(texture); // Create a graphical text to display - const auto font = sf::Font::openFromFile(resourcePath() / "tuffy.ttf").value(); - sf::Text text(font, "Hello SFML", 50); + const sf::Font font(resourcePath() / "tuffy.ttf"); + sf::Text text(font, "Hello SFML", 50); text.setFillColor(sf::Color::Black); // Load a music to play diff --git a/tools/xcode/templates/SFML/SFML CLT.xctemplate/main.cpp b/tools/xcode/templates/SFML/SFML CLT.xctemplate/main.cpp index 045a00b792..3eaea6cf92 100644 --- a/tools/xcode/templates/SFML/SFML CLT.xctemplate/main.cpp +++ b/tools/xcode/templates/SFML/SFML CLT.xctemplate/main.cpp @@ -24,16 +24,16 @@ int main() sf::RenderWindow window(sf::VideoMode({800, 600}), "SFML window"); // Set the Icon - const auto icon = sf::Image::loadFromFile("icon.png").value(); + const sf::Image icon("icon.png"); window.setIcon(icon); // Load a sprite to display - const auto texture = sf::Texture::loadFromFile("background.jpg").value(); - sf::Sprite sprite(texture); + const sf::Texture texture("background.jpg"); + sf::Sprite sprite(texture); // Create a graphical text to display - const auto font = sf::Font::openFromFile("tuffy.ttf").value(); - sf::Text text(font, "Hello SFML", 50); + const sf::Font font("tuffy.ttf"); + sf::Text text(font, "Hello SFML", 50); text.setFillColor(sf::Color::Black); // Load a music to play