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 | 93 +++-- include/SFML/Audio/Music.hpp | 132 +++--- include/SFML/Audio/OutputSoundFile.hpp | 40 +- include/SFML/Audio/Sound.hpp | 2 +- include/SFML/Audio/SoundBuffer.hpp | 145 ++++--- include/SFML/Graphics/Font.hpp | 146 +++---- include/SFML/Graphics/Image.hpp | 113 +++-- include/SFML/Graphics/RenderTexture.hpp | 45 +- include/SFML/Graphics/RenderWindow.hpp | 10 +- include/SFML/Graphics/Shader.hpp | 391 +++++++++--------- include/SFML/Graphics/Sprite.hpp | 2 +- include/SFML/Graphics/Text.hpp | 2 +- include/SFML/Graphics/Texture.hpp | 344 +++++++-------- include/SFML/System/FileInputStream.hpp | 20 +- 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 | 385 ++++++++--------- 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 | 270 ++++++------ 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 | 215 +++++----- 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, 2360 insertions(+), 2263 deletions(-) diff --git a/doc/mainpage.hpp b/doc/mainpage.hpp index 561deb458..2750e097c 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 abc025e29..0078e5820 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 327f3a916..ae4def03b 100644 --- a/examples/cocoa/CocoaAppDelegate.mm +++ b/examples/cocoa/CocoaAppDelegate.mm @@ -52,9 +52,9 @@ struct SFMLmainWindow 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 263a7b382..b14d413e2 100644 --- a/examples/event_handling/EventHandling.cpp +++ b/examples/event_handling/EventHandling.cpp @@ -316,7 +316,7 @@ private: // 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 fb02ec8fe..8a356a5f6 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 011ef33cb..abd1fea76 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 ed369639d..6d7f77332 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 2faeb9be5..8a7c6f2cb 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 5e4543c09..cedb20b26 100644 --- a/examples/shader/Shader.cpp +++ b/examples/shader/Shader.cpp @@ -278,69 +278,66 @@ private: //////////////////////////////////////////////////////////// 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 99f95ccc2..fe17d3114 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 b98e0ffcb..90787aa37 100644 --- a/examples/sound_effects/SoundEffects.cpp +++ b/examples/sound_effects/SoundEffects.cpp @@ -115,23 +115,23 @@ public: 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 @@ public: // 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 @@ public: 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 @@ public: 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 @@ public: // 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 @@ public: 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 @@ public: 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 @@ public: // 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 @@ public: 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 @@ public: // 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 @@ protected: 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 @@ private: 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 4d5b0ab08..0aa62a67c 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 315b6f8fd..4157eb9d9 100644 --- a/examples/vulkan/Vulkan.cpp +++ b/examples/vulkan/Vulkan.cpp @@ -923,17 +923,17 @@ public: // 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 @@ public: // 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 @@ public: 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 c5679cf05..b5c9f9e63 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 07ff47b17..1544339c6 100644 --- a/include/SFML/Audio/InputSoundFile.hpp +++ b/include/SFML/Audio/InputSoundFile.hpp @@ -33,7 +33,6 @@ #include #include -#include #include #include @@ -61,6 +60,51 @@ public: //////////////////////////////////////////////////////////// InputSoundFile() = default; + //////////////////////////////////////////////////////////// + /// \brief Construct a sound file from the disk for reading + /// + /// The supported audio formats are: WAV (PCM only), OGG/Vorbis, FLAC, MP3. + /// The supported sample sizes for FLAC and WAV are 8, 16, 24 and 32 bit. + /// + /// Because of minimp3_ex limitation, for MP3 files with big (>16kb) APEv2 tag, + /// it may not be properly removed, tag data will be treated as MP3 data + /// and there is a low chance of garbage decoded at the end of file. + /// See also: https://github.com/lieff/minimp3 + /// + /// \param filename Path of the sound file to load + /// + /// \throws std::runtime_error if opening the file was unsuccessful + /// + //////////////////////////////////////////////////////////// + InputSoundFile(const std::filesystem::path& filename); + + //////////////////////////////////////////////////////////// + /// \brief Construct a sound file in memory for reading + /// + /// The supported audio formats are: WAV (PCM only), OGG/Vorbis, FLAC. + /// The supported sample sizes for FLAC and WAV are 8, 16, 24 and 32 bit. + /// + /// \param data Pointer to the file data in memory + /// \param sizeInBytes Size of the data to load, in bytes + /// + /// \throws std::runtime_error if opening the file was unsuccessful + /// + //////////////////////////////////////////////////////////// + InputSoundFile(const void* data, std::size_t sizeInBytes); + + //////////////////////////////////////////////////////////// + /// \brief Construct a sound file from a custom stream for reading + /// + /// The supported audio formats are: WAV (PCM only), OGG/Vorbis, FLAC. + /// The supported sample sizes for FLAC and WAV are 8, 16, 24 and 32 bit. + /// + /// \param stream Source stream to read from + /// + /// \throws std::runtime_error if opening the file was unsuccessful + /// + //////////////////////////////////////////////////////////// + InputSoundFile(InputStream& stream); + //////////////////////////////////////////////////////////// /// \brief Open a sound file from the disk for reading /// @@ -106,51 +150,6 @@ public: //////////////////////////////////////////////////////////// [[nodiscard]] bool openFromStream(InputStream& stream); - //////////////////////////////////////////////////////////// - /// \brief Create a sound file from the disk for reading - /// - /// The supported audio formats are: WAV (PCM only), OGG/Vorbis, FLAC, MP3. - /// The supported sample sizes for FLAC and WAV are 8, 16, 24 and 32 bit. - /// - /// Because of minimp3_ex limitation, for MP3 files with big (>16kb) APEv2 tag, - /// it may not be properly removed, tag data will be treated as MP3 data - /// and there is a low chance of garbage decoded at the end of file. - /// See also: https://github.com/lieff/minimp3 - /// - /// \param filename Path of the sound file to load - /// - /// \return Input sound file if the file was successfully opened, otherwise `std::nullopt` - /// - //////////////////////////////////////////////////////////// - [[nodiscard]] static std::optional createFromFile(const std::filesystem::path& filename); - - //////////////////////////////////////////////////////////// - /// \brief Create a sound file in memory for reading - /// - /// The supported audio formats are: WAV (PCM only), OGG/Vorbis, FLAC. - /// The supported sample sizes for FLAC and WAV are 8, 16, 24 and 32 bit. - /// - /// \param data Pointer to the file data in memory - /// \param sizeInBytes Size of the data to load, in bytes - /// - /// \return Input sound file if the file was successfully opened, otherwise `std::nullopt` - /// - //////////////////////////////////////////////////////////// - [[nodiscard]] static std::optional createFromMemory(const void* data, std::size_t sizeInBytes); - - //////////////////////////////////////////////////////////// - /// \brief Create a sound file from a custom stream for reading - /// - /// The supported audio formats are: WAV (PCM only), OGG/Vorbis, FLAC. - /// The supported sample sizes for FLAC and WAV are 8, 16, 24 and 32 bit. - /// - /// \param stream Source stream to read from - /// - /// \return Input sound file if the file was successfully opened, otherwise `std::nullopt` - /// - //////////////////////////////////////////////////////////// - [[nodiscard]] static std::optional createFromStream(InputStream& stream); - //////////////////////////////////////////////////////////// /// \brief Get the total number of audio samples in the file /// @@ -311,7 +310,7 @@ private: /// 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 546fe220b..54e6b6c10 100644 --- a/include/SFML/Audio/Music.hpp +++ b/include/SFML/Audio/Music.hpp @@ -74,6 +74,71 @@ public: //////////////////////////////////////////////////////////// Music(); + //////////////////////////////////////////////////////////// + /// \brief Construct a music from an audio file + /// + /// This function doesn't start playing the music (call play() + /// to do so). + /// See the documentation of sf::InputSoundFile for the list + /// of supported formats. + /// + /// \warning Since the music is not loaded at once but rather + /// streamed continuously, the file must remain accessible until + /// the sf::Music object loads a new music or is destroyed. + /// + /// \param filename Path of the music file to open + /// + /// \throws std::runtime_error if loading was unsuccessful + /// + /// \see openFromMemory, openFromStream + /// + //////////////////////////////////////////////////////////// + Music(const std::filesystem::path& filename); + + //////////////////////////////////////////////////////////// + /// \brief Construct a music from an audio file in memory + /// + /// This function doesn't start playing the music (call play() + /// to do so). + /// See the documentation of sf::InputSoundFile for the list + /// of supported formats. + /// + /// \warning Since the music is not loaded at once but rather streamed + /// continuously, the \a data buffer must remain accessible until + /// the sf::Music object loads a new music or is destroyed. That is, + /// you can't deallocate the buffer right after calling this function. + /// + /// \param data Pointer to the file data in memory + /// \param sizeInBytes Size of the data to load, in bytes + /// + /// \throws std::runtime_error if loading was unsuccessful + /// + /// \see openFromFile, openFromStream + /// + //////////////////////////////////////////////////////////// + Music(const void* data, std::size_t sizeInBytes); + + //////////////////////////////////////////////////////////// + /// \brief Construct a music from an audio file in a custom stream + /// + /// This function doesn't start playing the music (call play() + /// to do so). + /// See the documentation of sf::InputSoundFile for the list + /// of supported formats. + /// + /// \warning Since the music is not loaded at once but rather + /// streamed continuously, the \a stream must remain accessible + /// until the sf::Music object loads a new music or is destroyed. + /// + /// \param stream Source stream to read from + /// + /// \throws std::runtime_error if loading was unsuccessful + /// + /// \see openFromFile, openFromMemory + /// + //////////////////////////////////////////////////////////// + Music(InputStream& stream); + //////////////////////////////////////////////////////////// /// \brief Destructor /// @@ -157,71 +222,6 @@ public: //////////////////////////////////////////////////////////// [[nodiscard]] bool openFromStream(InputStream& stream); - //////////////////////////////////////////////////////////// - /// \brief Create a music from an audio file - /// - /// This function doesn't start playing the music (call play() - /// to do so). - /// See the documentation of sf::InputSoundFile for the list - /// of supported formats. - /// - /// \warning Since the music is not loaded at once but rather - /// streamed continuously, the file must remain accessible until - /// the sf::Music object loads a new music or is destroyed. - /// - /// \param filename Path of the music file to open - /// - /// \return Music if loading succeeded, `std::nullopt` if it failed - /// - /// \see createFromMemory, createFromStream - /// - //////////////////////////////////////////////////////////// - [[nodiscard]] static std::optional createFromFile(const std::filesystem::path& filename); - - //////////////////////////////////////////////////////////// - /// \brief Create a music from an audio file in memory - /// - /// This function doesn't start playing the music (call play() - /// to do so). - /// See the documentation of sf::InputSoundFile for the list - /// of supported formats. - /// - /// \warning Since the music is not loaded at once but rather streamed - /// continuously, the \a data buffer must remain accessible until - /// the sf::Music object loads a new music or is destroyed. That is, - /// you can't deallocate the buffer right after calling this function. - /// - /// \param data Pointer to the file data in memory - /// \param sizeInBytes Size of the data to load, in bytes - /// - /// \return Music if loading succeeded, `std::nullopt` if it failed - /// - /// \see createFromFile, createFromStream - /// - //////////////////////////////////////////////////////////// - [[nodiscard]] static std::optional createFromMemory(const void* data, std::size_t sizeInBytes); - - //////////////////////////////////////////////////////////// - /// \brief Create a music from an audio file in a custom stream - /// - /// This function doesn't start playing the music (call play() - /// to do so). - /// See the documentation of sf::InputSoundFile for the list - /// of supported formats. - /// - /// \warning Since the music is not loaded at once but rather - /// streamed continuously, the \a stream must remain accessible - /// until the sf::Music object loads a new music or is destroyed. - /// - /// \param stream Source stream to read from - /// - /// \return Music if loading succeeded, `std::nullopt` if it failed - /// - /// \see createFromFile, createFromMemory - /// - //////////////////////////////////////////////////////////// - [[nodiscard]] static std::optional createFromStream(InputStream& stream); - //////////////////////////////////////////////////////////// /// \brief Get the total duration of the music /// @@ -360,7 +360,7 @@ private: /// 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 cbbc530bc..7009179e8 100644 --- a/include/SFML/Audio/OutputSoundFile.hpp +++ b/include/SFML/Audio/OutputSoundFile.hpp @@ -34,7 +34,6 @@ #include #include -#include #include #include @@ -58,6 +57,24 @@ public: //////////////////////////////////////////////////////////// OutputSoundFile() = default; + //////////////////////////////////////////////////////////// + /// \brief Construct the sound file from the disk for writing + /// + /// The supported audio formats are: WAV, OGG/Vorbis, FLAC. + /// + /// \param filename Path of the sound file to write + /// \param sampleRate Sample rate of the sound + /// \param channelCount Number of channels in the sound + /// \param channelMap Map of position in sample frame to sound channel + /// + /// \throws std::runtime_error if the file could not be opened successfully + /// + //////////////////////////////////////////////////////////// + OutputSoundFile(const std::filesystem::path& filename, + unsigned int sampleRate, + unsigned int channelCount, + const std::vector& channelMap); + //////////////////////////////////////////////////////////// /// \brief Open the sound file from the disk for writing /// @@ -76,25 +93,6 @@ public: unsigned int channelCount, const std::vector& channelMap); - //////////////////////////////////////////////////////////// - /// \brief Create the sound file from the disk for writing - /// - /// The supported audio formats are: WAV, OGG/Vorbis, FLAC. - /// - /// \param filename Path of the sound file to write - /// \param sampleRate Sample rate of the sound - /// \param channelCount Number of channels in the sound - /// \param channelMap Map of position in sample frame to sound channel - /// - /// \return Output sound file if the file was successfully opened - /// - //////////////////////////////////////////////////////////// - [[nodiscard]] static std::optional createFromFile( - 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 @@ private: /// 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 95f5dbeab..2fd6e25b9 100644 --- a/include/SFML/Audio/Sound.hpp +++ b/include/SFML/Audio/Sound.hpp @@ -274,7 +274,7 @@ private: /// /// 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 1a0b088ce..762fecdd8 100644 --- a/include/SFML/Audio/SoundBuffer.hpp +++ b/include/SFML/Audio/SoundBuffer.hpp @@ -34,7 +34,6 @@ #include #include -#include #include #include @@ -72,6 +71,74 @@ public: //////////////////////////////////////////////////////////// SoundBuffer(const SoundBuffer& copy); + //////////////////////////////////////////////////////////// + /// \brief Construct the sound buffer from a file + /// + /// See the documentation of sf::InputSoundFile for the list + /// of supported formats. + /// + /// \param filename Path of the sound file to load + /// + /// \throws std::runtime_error if loading was unsuccessful + /// + /// \see loadFromMemory, loadFromStream, loadFromSamples, saveToFile + /// + //////////////////////////////////////////////////////////// + SoundBuffer(const std::filesystem::path& filename); + + //////////////////////////////////////////////////////////// + /// \brief Construct the sound buffer from a file in memory + /// + /// See the documentation of sf::InputSoundFile for the list + /// of supported formats. + /// + /// \param data Pointer to the file data in memory + /// \param sizeInBytes Size of the data to load, in bytes + /// + /// \throws std::runtime_error if loading was unsuccessful + /// + /// \see loadFromFile, loadFromStream, loadFromSamples + /// + //////////////////////////////////////////////////////////// + SoundBuffer(const void* data, std::size_t sizeInBytes); + + //////////////////////////////////////////////////////////// + /// \brief Construct the sound buffer from a custom stream + /// + /// See the documentation of sf::InputSoundFile for the list + /// of supported formats. + /// + /// \param stream Source stream to read from + /// + /// \throws std::runtime_error if loading was unsuccessful + /// + /// \see loadFromFile, loadFromMemory, loadFromSamples + /// + //////////////////////////////////////////////////////////// + SoundBuffer(InputStream& stream); + + //////////////////////////////////////////////////////////// + /// \brief Construct the sound buffer from an array of audio samples + /// + /// The assumed format of the audio samples is 16 bit signed integer. + /// + /// \param samples Pointer to the array of samples in memory + /// \param sampleCount Number of samples in the array + /// \param channelCount Number of channels (1 = mono, 2 = stereo, ...) + /// \param sampleRate Sample rate (number of samples to play per second) + /// \param channelMap Map of position in sample frame to sound channel + /// + /// \throws std::runtime_error if loading was unsuccessful + /// + /// \see loadFromFile, loadFromMemory, saveToFile + /// + //////////////////////////////////////////////////////////// + SoundBuffer(const std::int16_t* samples, + std::uint64_t sampleCount, + unsigned int channelCount, + unsigned int sampleRate, + const std::vector& channelMap); + //////////////////////////////////////////////////////////// /// \brief Destructor /// @@ -146,75 +213,6 @@ public: unsigned int sampleRate, const std::vector& channelMap); - //////////////////////////////////////////////////////////// - /// \brief Create the sound buffer from a file - /// - /// See the documentation of sf::InputSoundFile for the list - /// of supported formats. - /// - /// \param filename Path of the sound file to load - /// - /// \return Sound buffer if loading succeeded, `std::nullopt` if it failed - /// - /// \see createFromMemory, createFromStream, createFromSamples, saveToFile - /// - //////////////////////////////////////////////////////////// - [[nodiscard]] static std::optional createFromFile(const std::filesystem::path& filename); - - //////////////////////////////////////////////////////////// - /// \brief Create the sound buffer from a file in memory - /// - /// See the documentation of sf::InputSoundFile for the list - /// of supported formats. - /// - /// \param data Pointer to the file data in memory - /// \param sizeInBytes Size of the data to load, in bytes - /// - /// \return Sound buffer if loading succeeded, `std::nullopt` if it failed - /// - /// \see createFromFile, createFromStream, createFromSamples - /// - //////////////////////////////////////////////////////////// - [[nodiscard]] static std::optional createFromMemory(const void* data, std::size_t sizeInBytes); - - //////////////////////////////////////////////////////////// - /// \brief Create the sound buffer from a custom stream - /// - /// See the documentation of sf::InputSoundFile for the list - /// of supported formats. - /// - /// \param stream Source stream to read from - /// - /// \return Sound buffer if loading succeeded, `std::nullopt` if it failed - /// - /// \see createFromFile, createFromMemory, createFromSamples - /// - //////////////////////////////////////////////////////////// - [[nodiscard]] static std::optional createFromStream(InputStream& stream); - - //////////////////////////////////////////////////////////// - /// \brief Create the sound buffer from an array of audio samples - /// - /// The assumed format of the audio samples is 16 bits signed integer. - /// - /// \param samples Pointer to the array of samples in memory - /// \param sampleCount Number of samples in the array - /// \param channelCount Number of channels (1 = mono, 2 = stereo, ...) - /// \param sampleRate Sample rate (number of samples to play per second) - /// \param channelMap Map of position in sample frame to sound channel - /// - /// \return Sound buffer if loading succeeded, `std::nullopt` if it failed - /// - /// \see createFromFile, createFromMemory, saveToFile - /// - //////////////////////////////////////////////////////////// - [[nodiscard]] static std::optional createFromSamples( - 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 @@ public: /// /// \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 @@ private: /// 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 @@ private: /// 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 a36bb73dd..a2021749e 100644 --- a/include/SFML/Graphics/Font.hpp +++ b/include/SFML/Graphics/Font.hpp @@ -37,7 +37,6 @@ #include #include -#include #include #include #include @@ -81,6 +80,71 @@ public: //////////////////////////////////////////////////////////// Font() = default; + //////////////////////////////////////////////////////////// + /// \brief Construct the font from a file + /// + /// The supported font formats are: TrueType, Type 1, CFF, + /// OpenType, SFNT, X11 PCF, Windows FNT, BDF, PFR and Type 42. + /// Note that this function knows nothing about the standard + /// fonts installed on the user's system, thus you can't + /// load them directly. + /// + /// \warning SFML cannot preload all the font data in this + /// function, so the file has to remain accessible until + /// the sf::Font object opens a new font or is destroyed. + /// + /// \param filename Path of the font file to open + /// + /// \throws std::runtime_error if opening was unsuccessful + /// + /// \see openFromFile, openFromMemory, openFromStream + /// + //////////////////////////////////////////////////////////// + Font(const std::filesystem::path& filename); + + //////////////////////////////////////////////////////////// + /// \brief Construct the font from a file in memory + /// + /// The supported font formats are: TrueType, Type 1, CFF, + /// OpenType, SFNT, X11 PCF, Windows FNT, BDF, PFR and Type 42. + /// + /// \warning SFML cannot preload all the font data in this + /// function, so the buffer pointed by \a data has to remain + /// valid until the sf::Font object opens a new font or + /// is destroyed. + /// + /// \param data Pointer to the file data in memory + /// \param sizeInBytes Size of the data to load, in bytes + /// + /// \throws std::runtime_error if loading was unsuccessful + /// + /// \see openFromFile, openFromMemory, openFromStream + /// + //////////////////////////////////////////////////////////// + Font(const void* data, std::size_t sizeInBytes); + + //////////////////////////////////////////////////////////// + /// \brief Construct the font from a custom stream + /// + /// The supported font formats are: TrueType, Type 1, CFF, + /// OpenType, SFNT, X11 PCF, Windows FNT, BDF, PFR and Type 42. + /// Warning: SFML cannot preload all the font data in this + /// function, so the contents of \a stream have to remain + /// valid as long as the font is used. + /// + /// \warning SFML cannot preload all the font data in this + /// function, so the stream has to remain accessible until + /// the sf::Font object opens a new font or is destroyed. + /// + /// \param stream Source stream to read from + /// + /// \throws std::runtime_error if loading was unsuccessful + /// + /// \see openFromFile, openFromMemory, openFromStream + /// + //////////////////////////////////////////////////////////// + Font(InputStream& stream); + //////////////////////////////////////////////////////////// /// \brief Open the font from a file /// @@ -92,11 +156,11 @@ public: /// /// \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 /// - /// \return True if loading succeeded, false if it failed + /// \return True if opening succeeded, false if it failed /// /// \see openFromMemory, openFromStream /// @@ -111,13 +175,13 @@ public: /// /// \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 + /// \return True if opening succeeded, false if it failed /// /// \see openFromFile, openFromStream /// @@ -129,84 +193,20 @@ public: /// /// The supported font formats are: TrueType, Type 1, CFF, /// OpenType, SFNT, X11 PCF, Windows FNT, BDF, PFR and Type 42. - /// Warning: SFML cannot preload all the font data in this - /// function, so the contents of \a stream have to remain - /// valid as long as the font is used. /// /// \warning SFML cannot preload all the font data in this /// function, so the stream has to remain accessible until - /// the sf::Font object 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 + /// \return True if opening succeeded, false if it failed /// /// \see openFromFile, openFromMemory /// //////////////////////////////////////////////////////////// [[nodiscard]] bool openFromStream(InputStream& stream); - //////////////////////////////////////////////////////////// - /// \brief Create the font from a file - /// - /// The supported font formats are: TrueType, Type 1, CFF, - /// OpenType, SFNT, X11 PCF, Windows FNT, BDF, PFR and Type 42. - /// Note that this function knows nothing about the standard - /// fonts installed on the user's system, thus you can't - /// load them directly. - /// - /// \warning SFML cannot preload all the font data in this - /// function, so the file has to remain accessible until - /// the sf::Font object is destroyed. - /// - /// \param filename Path of the font file to load - /// - /// \return Font if opening succeeded, `std::nullopt` if it failed - /// - /// \see createFromMemory, createFromStream - /// - //////////////////////////////////////////////////////////// - [[nodiscard]] static std::optional createFromFile(const std::filesystem::path& filename); - - //////////////////////////////////////////////////////////// - /// \brief Create the font from a file in memory - /// - /// The supported font formats are: TrueType, Type 1, CFF, - /// OpenType, SFNT, X11 PCF, Windows FNT, BDF, PFR and Type 42. - /// - /// \warning SFML cannot preload all the font data in this - /// function, so the buffer pointed by \a data has to remain - /// valid until the sf::Font object is destroyed. - /// - /// \param data Pointer to the file data in memory - /// \param sizeInBytes Size of the data to load, in bytes - /// - /// \return Font if opening succeeded, `std::nullopt` if it failed - /// - /// \see createFromFile, createFromStream - /// - //////////////////////////////////////////////////////////// - [[nodiscard]] static std::optional createFromMemory(const void* data, std::size_t sizeInBytes); - - //////////////////////////////////////////////////////////// - /// \brief Create the font from a custom stream - /// - /// The supported font formats are: TrueType, Type 1, CFF, - /// OpenType, SFNT, X11 PCF, Windows FNT, BDF, PFR and Type 42. - /// - /// \warning SFML cannot preload all the font data in this - /// function, so the stream has to remain accessible until - /// the sf::Font object is destroyed. - /// - /// \param stream Source stream to read from - /// - /// \return Font if opening succeeded, `std::nullopt` if it failed - /// - /// \see createFromFile, createFromMemory - /// - //////////////////////////////////////////////////////////// - [[nodiscard]] static std::optional createFromStream(InputStream& stream); - //////////////////////////////////////////////////////////// /// \brief Get the font information /// @@ -474,7 +474,7 @@ private: /// /// 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 @@ private: /// 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 8e41310e1..46d3053d4 100644 --- a/include/SFML/Graphics/Image.hpp +++ b/include/SFML/Graphics/Image.hpp @@ -59,6 +59,8 @@ public: /// /// Constructs an image with width 0 and height 0. /// + /// \see resize + /// //////////////////////////////////////////////////////////// Image() = default; @@ -85,6 +87,55 @@ public: //////////////////////////////////////////////////////////// Image(Vector2u size, const std::uint8_t* pixels); + //////////////////////////////////////////////////////////// + /// \brief Construct the image from a file on disk + /// + /// The supported image formats are bmp, png, tga, jpg, gif, + /// psd, hdr, pic and pnm. Some format options are not supported, + /// like jpeg with arithmetic coding or ASCII pnm. + /// + /// \param filename Path of the image file to load + /// + /// \throws std::runtime_error if loading was unsuccessful + /// + /// \see loadFromFile, loadFromMemory, loadFromStream + /// + //////////////////////////////////////////////////////////// + explicit Image(const std::filesystem::path& filename); + + //////////////////////////////////////////////////////////// + /// \brief Construct the image from a file in memory + /// + /// The supported image formats are bmp, png, tga, jpg, gif, + /// psd, hdr, pic and pnm. Some format options are not supported, + /// like jpeg with arithmetic coding or ASCII pnm. + /// + /// \param data Pointer to the file data in memory + /// \param size Size of the data to load, in bytes + /// + /// \throws std::runtime_error if loading was unsuccessful + /// + /// \see loadFromFile, loadFromMemory, loadFromStream + /// + //////////////////////////////////////////////////////////// + Image(const void* data, std::size_t size); + + //////////////////////////////////////////////////////////// + /// \brief Construct the image from a custom stream + /// + /// The supported image formats are bmp, png, tga, jpg, gif, + /// psd, hdr, pic and pnm. Some format options are not supported, + /// like jpeg with arithmetic coding or ASCII pnm. + /// + /// \param stream Source stream to read from + /// + /// \throws std::runtime_error if loading was unsuccessful + /// + /// \see loadFromFile, loadFromMemory, loadFromStream + /// + //////////////////////////////////////////////////////////// + explicit Image(InputStream& stream); + //////////////////////////////////////////////////////////// /// \brief Resize the image and fill it with a unique color /// @@ -138,7 +189,7 @@ public: /// /// \return True if loading was successful /// - /// \see loadFromFile, loadFromStream + /// \see loadFromFile, loadFromStream, saveToMemory /// //////////////////////////////////////////////////////////// [[nodiscard]] bool loadFromMemory(const void* data, std::size_t size); @@ -160,58 +211,6 @@ public: //////////////////////////////////////////////////////////// [[nodiscard]] bool loadFromStream(InputStream& stream); - //////////////////////////////////////////////////////////// - /// \brief Load the image from a file on disk - /// - /// The supported image formats are bmp, png, tga, jpg, gif, - /// psd, hdr, pic and pnm. Some format options are not supported, - /// like jpeg with arithmetic coding or ASCII pnm. - /// If this function fails, the image is left unchanged. - /// - /// \param filename Path of the image file to load - /// - /// \return Image if loading was successful, `std::nullopt` otherwise - /// - /// \see createFromMemory, createFromStream, saveToFile - /// - //////////////////////////////////////////////////////////// - [[nodiscard]] static std::optional createFromFile(const std::filesystem::path& filename); - - //////////////////////////////////////////////////////////// - /// \brief Load the image from a file in memory - /// - /// The supported image formats are bmp, png, tga, jpg, gif, - /// psd, hdr, pic and pnm. Some format options are not supported, - /// like jpeg with arithmetic coding or ASCII pnm. - /// If this function fails, the image is left unchanged. - /// - /// \param data Pointer to the file data in memory - /// \param size Size of the data to load, in bytes - /// - /// \return Image if loading was successful, `std::nullopt` otherwise - /// - /// \see createFromFile, createFromStream - /// - //////////////////////////////////////////////////////////// - [[nodiscard]] static std::optional createFromMemory(const void* data, std::size_t size); - - //////////////////////////////////////////////////////////// - /// \brief Load the image from a custom stream - /// - /// The supported image formats are bmp, png, tga, jpg, gif, - /// psd, hdr, pic and pnm. Some format options are not supported, - /// like jpeg with arithmetic coding or ASCII pnm. - /// If this function fails, the image is left unchanged. - /// - /// \param stream Source stream to read from - /// - /// \return Image if loading was successful, `std::nullopt` otherwise - /// - /// \see createFromFile, createFromMemory - /// - //////////////////////////////////////////////////////////// - [[nodiscard]] static std::optional createFromStream(InputStream& stream); - //////////////////////////////////////////////////////////// /// \brief Save the image to a file on disk /// @@ -224,7 +223,7 @@ public: /// /// \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 @@ public: /// \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 @@ private: /// 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 @@ private: /// 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 eb440c2fa..fc2d6a910 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 @@ public: //////////////////////////////////////////////////////////// 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 @@ public: /// \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 + /// \return True if resizing has been successful, false if it failed /// //////////////////////////////////////////////////////////// - [[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` - /// - //////////////////////////////////////////////////////////// - [[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 @@ private: /// 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 962bece76..bd4ce969f 100644 --- a/include/SFML/Graphics/RenderWindow.hpp +++ b/include/SFML/Graphics/RenderWindow.hpp @@ -87,7 +87,7 @@ public: 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 @@ public: /// \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 @@ public: /// \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 @@ private: /// 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 9133b0ec8..119cb1df0 100644 --- a/include/SFML/Graphics/Shader.hpp +++ b/include/SFML/Graphics/Shader.hpp @@ -34,7 +34,6 @@ #include #include -#include #include #include #include @@ -126,6 +125,198 @@ public: //////////////////////////////////////////////////////////// Shader& operator=(Shader&& right) noexcept; + //////////////////////////////////////////////////////////// + /// \brief Construct from a shader file + /// + /// This constructor loads a single shader, vertex, geometry or + /// fragment, identified by the second argument. + /// The source must be a text file containing a valid + /// shader in GLSL language. GLSL is a C-like language + /// dedicated to OpenGL shaders; you'll probably need to + /// read a good documentation for it before writing your + /// own shaders. + /// + /// \param filename Path of the vertex, geometry or fragment shader file to load + /// \param type Type of shader (vertex, geometry or fragment) + /// + /// \throws std::runtime_error if loading was unsuccessful + /// + /// \see loadFromFile, loadFromMemory, loadFromStream + /// + //////////////////////////////////////////////////////////// + Shader(const std::filesystem::path& filename, Type type); + + //////////////////////////////////////////////////////////// + /// \brief Construct from vertex and fragment shader files + /// + /// This constructor loads both the vertex and the fragment + /// shaders. If one of them fails to load, the shader is left + /// empty (the valid shader is unloaded). + /// The sources must be text files containing valid shaders + /// in GLSL language. GLSL is a C-like language dedicated to + /// OpenGL shaders; you'll probably need to read a good documentation + /// for it before writing your own shaders. + /// + /// \param vertexShaderFilename Path of the vertex shader file to load + /// \param fragmentShaderFilename Path of the fragment shader file to load + /// + /// \throws std::runtime_error if loading was unsuccessful + /// + /// \see loadFromFile, loadFromMemory, loadFromStream + /// + //////////////////////////////////////////////////////////// + Shader(const std::filesystem::path& vertexShaderFilename, const std::filesystem::path& fragmentShaderFilename); + + //////////////////////////////////////////////////////////// + /// \brief Construct from vertex, geometry and fragment shader files + /// + /// This constructor loads the vertex, geometry and fragment + /// shaders. If one of them fails to load, the shader is left + /// empty (the valid shader is unloaded). + /// The sources must be text files containing valid shaders + /// in GLSL language. GLSL is a C-like language dedicated to + /// OpenGL shaders; you'll probably need to read a good documentation + /// for it before writing your own shaders. + /// + /// \param vertexShaderFilename Path of the vertex shader file to load + /// \param geometryShaderFilename Path of the geometry shader file to load + /// \param fragmentShaderFilename Path of the fragment shader file to load + /// + /// \throws std::runtime_error if loading was unsuccessful + /// + /// \see loadFromFile, loadFromMemory, loadFromStream + /// + //////////////////////////////////////////////////////////// + Shader(const std::filesystem::path& vertexShaderFilename, + const std::filesystem::path& geometryShaderFilename, + const std::filesystem::path& fragmentShaderFilename); + + //////////////////////////////////////////////////////////// + /// \brief Construct from shader in memory + /// + /// This constructor loads a single shader, vertex, geometry + /// or fragment, identified by the second argument. + /// The source code must be a valid shader in GLSL language. + /// GLSL is a C-like language dedicated to OpenGL shaders; + /// you'll probably need to read a good documentation for + /// it before writing your own shaders. + /// + /// \param shader String containing the source code of the shader + /// \param type Type of shader (vertex, geometry or fragment) + /// + /// \throws std::runtime_error if loading was unsuccessful + /// + /// \see loadFromFile, loadFromMemory, loadFromStream + /// + //////////////////////////////////////////////////////////// + Shader(std::string_view shader, Type type); + + //////////////////////////////////////////////////////////// + /// \brief Construct from vertex and fragment shaders in memory + /// + /// This constructor loads both the vertex and the fragment + /// shaders. If one of them fails to load, the shader is left + /// empty (the valid shader is unloaded). + /// The sources must be valid shaders in GLSL language. GLSL is + /// a C-like language dedicated to OpenGL shaders; you'll + /// probably need to read a good documentation for it before + /// writing your own shaders. + /// + /// \param vertexShader String containing the source code of the vertex shader + /// \param fragmentShader String containing the source code of the fragment shader + /// + /// \throws std::runtime_error if loading was unsuccessful + /// + /// \see loadFromFile, loadFromMemory, loadFromStream + /// + //////////////////////////////////////////////////////////// + Shader(std::string_view vertexShader, std::string_view fragmentShader); + + //////////////////////////////////////////////////////////// + /// \brief Construct from vertex, geometry and fragment shaders in memory + /// + /// This constructor loads the vertex, geometry and fragment + /// shaders. If one of them fails to load, the shader is left + /// empty (the valid shader is unloaded). + /// The sources must be valid shaders in GLSL language. GLSL is + /// a C-like language dedicated to OpenGL shaders; you'll + /// probably need to read a good documentation for it before + /// writing your own shaders. + /// + /// \param vertexShader String containing the source code of the vertex shader + /// \param geometryShader String containing the source code of the geometry shader + /// \param fragmentShader String containing the source code of the fragment shader + /// + /// \throws std::runtime_error if loading was unsuccessful + /// + /// \see loadFromFile, loadFromMemory, loadFromStream + /// + //////////////////////////////////////////////////////////// + Shader(std::string_view vertexShader, std::string_view geometryShader, std::string_view fragmentShader); + + //////////////////////////////////////////////////////////// + /// \brief Construct from a shader stream + /// + /// This constructor loads a single shader, vertex, geometry + /// or fragment, identified by the second argument. + /// The source code must be a valid shader in GLSL language. + /// GLSL is a C-like language dedicated to OpenGL shaders; + /// you'll probably need to read a good documentation for it + /// before writing your own shaders. + /// + /// \param stream Source stream to read from + /// \param type Type of shader (vertex, geometry or fragment) + /// + /// \throws std::runtime_error if loading was unsuccessful + /// + /// \see loadFromFile, loadFromMemory, loadFromStream + /// + //////////////////////////////////////////////////////////// + Shader(InputStream& stream, Type type); + + //////////////////////////////////////////////////////////// + /// \brief Construct from vertex and fragment shader streams + /// + /// This constructor loads both the vertex and the fragment + /// shaders. If one of them fails to load, the shader is left + /// empty (the valid shader is unloaded). + /// The source codes must be valid shaders in GLSL language. + /// GLSL is a C-like language dedicated to OpenGL shaders; + /// you'll probably need to read a good documentation for + /// it before writing your own shaders. + /// + /// \param vertexShaderStream Source stream to read the vertex shader from + /// \param fragmentShaderStream Source stream to read the fragment shader from + /// + /// \throws std::runtime_error if loading was unsuccessful + /// + /// \see loadFromFile, loadFromMemory, loadFromStream + /// + //////////////////////////////////////////////////////////// + Shader(InputStream& vertexShaderStream, InputStream& fragmentShaderStream); + + //////////////////////////////////////////////////////////// + /// \brief Construct from vertex, geometry and fragment shader streams + /// + /// This constructor loads the vertex, geometry and fragment + /// shaders. If one of them fails to load, the shader is left + /// empty (the valid shader is unloaded). + /// The source codes must be valid shaders in GLSL language. + /// GLSL is a C-like language dedicated to OpenGL shaders; + /// you'll probably need to read a good documentation for + /// it before writing your own shaders. + /// + /// \param vertexShaderStream Source stream to read the vertex shader from + /// \param geometryShaderStream Source stream to read the geometry shader from + /// \param fragmentShaderStream Source stream to read the fragment shader from + /// + /// \throws std::runtime_error if loading was unsuccessful + /// + /// \see loadFromFile, loadFromMemory, loadFromStream + /// + //////////////////////////////////////////////////////////// + Shader(InputStream& vertexShaderStream, InputStream& geometryShaderStream, InputStream& fragmentShaderStream); + //////////////////////////////////////////////////////////// /// \brief Load the vertex, geometry or fragment shader from a file /// @@ -323,204 +514,6 @@ public: InputStream& geometryShaderStream, InputStream& fragmentShaderStream); - //////////////////////////////////////////////////////////// - /// \brief Load the vertex, geometry or fragment shader from a file - /// - /// This function loads a single shader, vertex, geometry or - /// fragment, identified by the second argument. - /// The source must be a text file containing a valid - /// shader in GLSL language. GLSL is a C-like language - /// dedicated to OpenGL shaders; you'll probably need to - /// read a good documentation for it before writing your - /// own shaders. - /// - /// \param filename Path of the vertex, geometry or fragment shader file to load - /// \param type Type of shader (vertex, geometry or fragment) - /// - /// \return Shader if loading succeeded, `std::nullopt` if it failed - /// - /// \see createFromMemory, createFromStream - /// - //////////////////////////////////////////////////////////// - [[nodiscard]] static std::optional createFromFile(const std::filesystem::path& filename, Type type); - - //////////////////////////////////////////////////////////// - /// \brief Load both the vertex and fragment shaders from files - /// - /// This function loads both the vertex and the fragment - /// shaders. If one of them fails to load, the shader is left - /// empty (the valid shader is unloaded). - /// The sources must be text files containing valid shaders - /// in GLSL language. GLSL is a C-like language dedicated to - /// OpenGL shaders; you'll probably need to read a good documentation - /// for it before writing your own shaders. - /// - /// \param vertexShaderFilename Path of the vertex shader file to load - /// \param fragmentShaderFilename Path of the fragment shader file to load - /// - /// \return Shader if loading succeeded, `std::nullopt` if it failed - /// - /// \see createFromMemory, createFromStream - /// - //////////////////////////////////////////////////////////// - [[nodiscard]] static std::optional createFromFile(const std::filesystem::path& vertexShaderFilename, - const std::filesystem::path& fragmentShaderFilename); - - //////////////////////////////////////////////////////////// - /// \brief Load the vertex, geometry and fragment shaders from files - /// - /// This function loads the vertex, geometry and fragment - /// shaders. If one of them fails to load, the shader is left - /// empty (the valid shader is unloaded). - /// The sources must be text files containing valid shaders - /// in GLSL language. GLSL is a C-like language dedicated to - /// OpenGL shaders; you'll probably need to read a good documentation - /// for it before writing your own shaders. - /// - /// \param vertexShaderFilename Path of the vertex shader file to load - /// \param geometryShaderFilename Path of the geometry shader file to load - /// \param fragmentShaderFilename Path of the fragment shader file to load - /// - /// \return Shader if loading succeeded, `std::nullopt` if it failed - /// - /// \see createFromMemory, createFromStream - /// - //////////////////////////////////////////////////////////// - [[nodiscard]] static std::optional createFromFile(const std::filesystem::path& vertexShaderFilename, - const std::filesystem::path& geometryShaderFilename, - const std::filesystem::path& fragmentShaderFilename); - - //////////////////////////////////////////////////////////// - /// \brief Load the vertex, geometry or fragment shader from a source code in memory - /// - /// This function loads a single shader, vertex, geometry - /// or fragment, identified by the second argument. - /// The source code must be a valid shader in GLSL language. - /// GLSL is a C-like language dedicated to OpenGL shaders; - /// you'll probably need to read a good documentation for - /// it before writing your own shaders. - /// - /// \param shader String containing the source code of the shader - /// \param type Type of shader (vertex, geometry or fragment) - /// - /// \return Shader if loading succeeded, `std::nullopt` if it failed - /// - /// \see createFromFile, createFromStream - /// - //////////////////////////////////////////////////////////// - [[nodiscard]] static std::optional createFromMemory(std::string_view shader, Type type); - - //////////////////////////////////////////////////////////// - /// \brief Load both the vertex and fragment shaders from source codes in memory - /// - /// This function loads both the vertex and the fragment - /// shaders. If one of them fails to load, the shader is left - /// empty (the valid shader is unloaded). - /// The sources must be valid shaders in GLSL language. GLSL is - /// a C-like language dedicated to OpenGL shaders; you'll - /// probably need to read a good documentation for it before - /// writing your own shaders. - /// - /// \param vertexShader String containing the source code of the vertex shader - /// \param fragmentShader String containing the source code of the fragment shader - /// - /// \return Shader if loading succeeded, `std::nullopt` if it failed - /// - /// \see createFromFile, createFromStream - /// - //////////////////////////////////////////////////////////// - [[nodiscard]] static std::optional createFromMemory(std::string_view vertexShader, std::string_view fragmentShader); - - //////////////////////////////////////////////////////////// - /// \brief Load the vertex, geometry and fragment shaders from source codes in memory - /// - /// This function loads the vertex, geometry and fragment - /// shaders. If one of them fails to load, the shader is left - /// empty (the valid shader is unloaded). - /// The sources must be valid shaders in GLSL language. GLSL is - /// a C-like language dedicated to OpenGL shaders; you'll - /// probably need to read a good documentation for it before - /// writing your own shaders. - /// - /// \param vertexShader String containing the source code of the vertex shader - /// \param geometryShader String containing the source code of the geometry shader - /// \param fragmentShader String containing the source code of the fragment shader - /// - /// \return Shader if loading succeeded, `std::nullopt` if it failed - /// - /// \see createFromFile, createFromStream - /// - //////////////////////////////////////////////////////////// - [[nodiscard]] static std::optional createFromMemory(std::string_view vertexShader, - std::string_view geometryShader, - std::string_view fragmentShader); - - //////////////////////////////////////////////////////////// - /// \brief Load the vertex, geometry or fragment shader from a custom stream - /// - /// This function loads a single shader, vertex, geometry - /// or fragment, identified by the second argument. - /// The source code must be a valid shader in GLSL language. - /// GLSL is a C-like language dedicated to OpenGL shaders; - /// you'll probably need to read a good documentation for it - /// before writing your own shaders. - /// - /// \param stream Source stream to read from - /// \param type Type of shader (vertex, geometry or fragment) - /// - /// \return Shader if loading succeeded, `std::nullopt` if it failed - /// - /// \see createFromFile, createFromMemory - /// - //////////////////////////////////////////////////////////// - [[nodiscard]] static std::optional createFromStream(InputStream& stream, Type type); - - //////////////////////////////////////////////////////////// - /// \brief Load both the vertex and fragment shaders from custom streams - /// - /// This function loads both the vertex and the fragment - /// shaders. If one of them fails to load, the shader is left - /// empty (the valid shader is unloaded). - /// The source codes must be valid shaders in GLSL language. - /// GLSL is a C-like language dedicated to OpenGL shaders; - /// you'll probably need to read a good documentation for - /// it before writing your own shaders. - /// - /// \param vertexShaderStream Source stream to read the vertex shader from - /// \param fragmentShaderStream Source stream to read the fragment shader from - /// - /// \return Shader if loading succeeded, `std::nullopt` if it failed - /// - /// \see createFromFile, createFromMemory - /// - //////////////////////////////////////////////////////////// - [[nodiscard]] static std::optional createFromStream(InputStream& vertexShaderStream, - InputStream& fragmentShaderStream); - - //////////////////////////////////////////////////////////// - /// \brief Load the vertex, geometry and fragment shaders from custom streams - /// - /// This function loads the vertex, geometry and fragment - /// shaders. If one of them fails to load, the shader is left - /// empty (the valid shader is unloaded). - /// The source codes must be valid shaders in GLSL language. - /// GLSL is a C-like language dedicated to OpenGL shaders; - /// you'll probably need to read a good documentation for - /// it before writing your own shaders. - /// - /// \param vertexShaderStream Source stream to read the vertex shader from - /// \param geometryShaderStream Source stream to read the geometry shader from - /// \param fragmentShaderStream Source stream to read the fragment shader from - /// - /// \return Shader if loading succeeded, `std::nullopt` if it failed - /// - /// \see createFromFile, createFromMemory - /// - //////////////////////////////////////////////////////////// - [[nodiscard]] static std::optional createFromStream(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 2b363a185..c35dee121 100644 --- a/include/SFML/Graphics/Sprite.hpp +++ b/include/SFML/Graphics/Sprite.hpp @@ -261,7 +261,7 @@ private: /// 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 d0a1dad63..9707c6642 100644 --- a/include/SFML/Graphics/Text.hpp +++ b/include/SFML/Graphics/Text.hpp @@ -469,7 +469,7 @@ private: /// 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 c497d3b0f..d83f73b69 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 @@ public: /// /// Creates a texture with width 0 and height 0. /// + /// \see resize + /// //////////////////////////////////////////////////////////// Texture(); @@ -96,6 +97,174 @@ public: //////////////////////////////////////////////////////////// Texture& operator=(Texture&&) noexcept; + //////////////////////////////////////////////////////////// + /// \brief Construct the texture from a file on disk + /// + /// The maximum size for a texture depends on the graphics + /// driver and can be retrieved with the getMaximumSize function. + /// + /// \param filename Path of the image file to load + /// \param sRgb True to enable sRGB conversion, false to disable it + /// + /// \throws std::runtime_error if loading was unsuccessful + /// + /// \see loadFromFile, loadFromMemory, loadFromStream, loadFromImage + /// + //////////////////////////////////////////////////////////// + explicit Texture(const std::filesystem::path& filename, bool sRgb = false); + + //////////////////////////////////////////////////////////// + /// \brief Construct the texture from a sub-rectangle of a file on disk + /// + /// The \a area argument can be used to load only a sub-rectangle + /// of the whole image. If you want the entire image then leave + /// the default value (which is an empty IntRect). + /// If the \a area rectangle crosses the bounds of the image, it + /// is adjusted to fit the image size. + /// + /// The maximum size for a texture depends on the graphics + /// driver and can be retrieved with the getMaximumSize function. + /// + /// \param filename Path of the image file to load + /// \param sRgb True to enable sRGB conversion, false to disable it + /// \param area Area of the image to load + /// + /// \throws std::runtime_error if loading was unsuccessful + /// + /// \see loadFromFile, loadFromMemory, loadFromStream, loadFromImage + /// + //////////////////////////////////////////////////////////// + Texture(const std::filesystem::path& filename, bool sRgb, const IntRect& area); + + //////////////////////////////////////////////////////////// + /// \brief Construct the texture from a file in memory + /// + /// The maximum size for a texture depends on the graphics + /// driver and can be retrieved with the getMaximumSize function. + /// + /// \param data Pointer to the file data in memory + /// \param size Size of the data to load, in bytes + /// \param sRgb True to enable sRGB conversion, false to disable it + /// + /// \throws std::runtime_error if loading was unsuccessful + /// + /// \see loadFromFile, loadFromMemory, loadFromStream, loadFromImage + /// + //////////////////////////////////////////////////////////// + Texture(const void* data, std::size_t size, bool sRgb = false); + + //////////////////////////////////////////////////////////// + /// \brief Construct the texture from a sub-rectangle of a file in memory + /// + /// The \a area argument can be used to load only a sub-rectangle + /// of the whole image. If you want the entire image then leave + /// the default value (which is an empty IntRect). + /// If the \a area rectangle crosses the bounds of the image, it + /// is adjusted to fit the image size. + /// + /// The maximum size for a texture depends on the graphics + /// driver and can be retrieved with the getMaximumSize function. + /// + /// \param data Pointer to the file data in memory + /// \param size Size of the data to load, in bytes + /// \param sRgb True to enable sRGB conversion, false to disable it + /// \param area Area of the image to load + /// + /// \throws std::runtime_error if loading was unsuccessful + /// + /// \see loadFromFile, loadFromMemory, loadFromStream, loadFromImage + /// + //////////////////////////////////////////////////////////// + Texture(const void* data, std::size_t size, bool sRgb, const IntRect& area); + + //////////////////////////////////////////////////////////// + /// \brief Construct the texture from a custom stream + /// + /// The maximum size for a texture depends on the graphics + /// driver and can be retrieved with the getMaximumSize function. + /// + /// \param stream Source stream to read from + /// \param sRgb True to enable sRGB conversion, false to disable it + /// + /// \throws std::runtime_error if loading was unsuccessful + /// + /// \see loadFromFile, loadFromMemory, loadFromStream, loadFromImage + /// + //////////////////////////////////////////////////////////// + explicit Texture(InputStream& stream, bool sRgb = false); + + //////////////////////////////////////////////////////////// + /// \brief Construct the texture from a sub-rectangle of a custom stream + /// + /// The \a area argument can be used to load only a sub-rectangle + /// of the whole image. If you want the entire image then leave + /// the default value (which is an empty IntRect). + /// If the \a area rectangle crosses the bounds of the image, it + /// is adjusted to fit the image size. + /// + /// The maximum size for a texture depends on the graphics + /// driver and can be retrieved with the getMaximumSize function. + /// + /// \param stream Source stream to read from + /// \param sRgb True to enable sRGB conversion, false to disable it + /// \param area Area of the image to load + /// + /// \throws std::runtime_error if loading was unsuccessful + /// + /// \see loadFromFile, loadFromMemory, loadFromStream, loadFromImage + /// + //////////////////////////////////////////////////////////// + Texture(InputStream& stream, bool sRgb, const IntRect& area); + + //////////////////////////////////////////////////////////// + /// \brief Construct the texture from an image + /// + /// The maximum size for a texture depends on the graphics + /// driver and can be retrieved with the getMaximumSize function. + /// + /// \param image Image to load into the texture + /// \param sRgb True to enable sRGB conversion, false to disable it + /// + /// \throws std::runtime_error if loading was unsuccessful + /// + /// \see loadFromFile, loadFromMemory, loadFromStream, loadFromImage + /// + //////////////////////////////////////////////////////////// + explicit Texture(const Image& image, bool sRgb = false); + + //////////////////////////////////////////////////////////// + /// \brief Construct the texture from a sub-rectangle of an image + /// + /// The \a area argument is used to load only a sub-rectangle + /// of the whole image. + /// If the \a area rectangle crosses the bounds of the image, it + /// is adjusted to fit the image size. + /// + /// The maximum size for a texture depends on the graphics + /// driver and can be retrieved with the getMaximumSize function. + /// + /// \param image Image to load into the texture + /// \param sRgb True to enable sRGB conversion, false to disable it + /// \param area Area of the image to load + /// + /// \throws std::runtime_error if loading was unsuccessful + /// + /// \see loadFromFile, loadFromMemory, loadFromStream, loadFromImage + /// + //////////////////////////////////////////////////////////// + Texture(const Image& image, bool sRgb, const IntRect& area); + + //////////////////////////////////////////////////////////// + /// \brief Construct the texture with a given size + /// + /// \param size Width and height of the texture + /// \param sRgb True to enable sRGB conversion, false to disable it + /// + /// \throws std::runtime_error if construction was unsuccessful + /// + //////////////////////////////////////////////////////////// + explicit Texture(Vector2u size, bool sRgb = false); + //////////////////////////////////////////////////////////// /// \brief Resize the texture /// @@ -104,7 +273,7 @@ public: /// \param size Width and height of the texture /// \param sRgb True to enable sRGB conversion, false to disable it /// - /// \return True if resizing was successful + /// \return True if resizing was successful, false if it failed /// //////////////////////////////////////////////////////////// [[nodiscard]] bool resize(Vector2u size, bool sRgb = false); @@ -112,15 +281,6 @@ public: //////////////////////////////////////////////////////////// /// \brief Load the texture from a file on disk /// - /// This function is a shortcut for the following code: - /// \code - /// sf::Image image; - /// if (!image.loadFromFile(filename)) - /// return false; - /// if (!texture.loadFromImage(image, area)) - /// return false; - /// \endcode - /// /// The \a area argument can be used to load only a sub-rectangle /// of the whole image. If you want the entire image then leave /// the default value (which is an empty IntRect). @@ -136,25 +296,16 @@ public: /// \param sRgb True to enable sRGB conversion, false to disable it /// \param area Area of the image to load /// - /// \return True if loading was successful + /// \return True if loading was successful, false if it failed /// /// \see loadFromMemory, loadFromStream, loadFromImage /// //////////////////////////////////////////////////////////// - [[nodiscard]] bool loadFromFile(const std::filesystem::path& filename, bool sRgb = false, const IntRect& area = IntRect()); + [[nodiscard]] bool loadFromFile(const std::filesystem::path& filename, bool sRgb = false, const IntRect& area = {}); //////////////////////////////////////////////////////////// /// \brief Load the texture from a file in memory /// - /// This function is a shortcut for the following code: - /// \code - /// sf::Image image; - /// if (!image.loadFromMemory(data, size)) - /// return false; - /// if (!texture.loadFromImage(image, area)) - /// return false; - /// \endcode - /// /// The \a area argument can be used to load only a sub-rectangle /// of the whole image. If you want the entire image then leave /// the default value (which is an empty IntRect). @@ -171,25 +322,16 @@ public: /// \param sRgb True to enable sRGB conversion, false to disable it /// \param area Area of the image to load /// - /// \return True if loading was successful + /// \return True if loading was successful, false if it failed /// /// \see loadFromFile, loadFromStream, loadFromImage /// //////////////////////////////////////////////////////////// - [[nodiscard]] bool loadFromMemory(const void* data, std::size_t size, bool sRgb = false, const IntRect& area = IntRect()); + [[nodiscard]] bool loadFromMemory(const void* data, std::size_t size, bool sRgb = false, const IntRect& area = {}); //////////////////////////////////////////////////////////// /// \brief Load the texture from a custom stream /// - /// This function is a shortcut for the following code: - /// \code - /// sf::Image image; - /// if (!image.loadFromStream(stream)) - /// return false; - /// if (!texture.loadFromImage(image, area)) - /// return false; - /// \endcode - /// /// The \a area argument can be used to load only a sub-rectangle /// of the whole image. If you want the entire image then leave /// the default value (which is an empty IntRect). @@ -205,12 +347,12 @@ public: /// \param sRgb True to enable sRGB conversion, false to disable it /// \param area Area of the image to load /// - /// \return True if loading was successful + /// \return True if loading was successful, false if it failed /// /// \see loadFromFile, loadFromMemory, loadFromImage /// //////////////////////////////////////////////////////////// - [[nodiscard]] bool loadFromStream(InputStream& stream, bool sRgb = false, const IntRect& area = IntRect()); + [[nodiscard]] bool loadFromStream(InputStream& stream, bool sRgb = false, const IntRect& area = {}); //////////////////////////////////////////////////////////// /// \brief Load the texture from an image @@ -230,132 +372,12 @@ public: /// \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 + /// \return True if loading was successful, false if it failed /// /// \see loadFromFile, loadFromMemory /// //////////////////////////////////////////////////////////// - [[nodiscard]] bool loadFromImage(const Image& image, bool sRgb = false, const IntRect& area = IntRect()); - - //////////////////////////////////////////////////////////// - /// \brief Create a texture - /// - /// \param size Width and height of the texture - /// \param sRgb True to enable sRGB conversion, false to disable it - /// - /// \return Texture if creation was successful, otherwise `std::nullopt` - /// - //////////////////////////////////////////////////////////// - [[nodiscard]] static std::optional create(Vector2u size, bool sRgb = false); - - //////////////////////////////////////////////////////////// - /// \brief Load the texture from a file on disk - /// - /// The \a area argument can be used to load only a sub-rectangle - /// of the whole image. If you want the entire image then leave - /// the default value (which is an empty IntRect). - /// If the \a area rectangle crosses the bounds of the image, it - /// is adjusted to fit the image size. - /// - /// The maximum size for a texture depends on the graphics - /// driver and can be retrieved with the getMaximumSize function. - /// - /// If this function fails, the texture is left unchanged. - /// - /// \param filename Path of the image file to load - /// \param sRgb True to enable sRGB conversion, false to disable it - /// \param area Area of the image to load - /// - /// \return Texture if loading was successful, otherwise `std::nullopt` - /// - /// \see createFromMemory, createFromStream, createFromImage - /// - //////////////////////////////////////////////////////////// - [[nodiscard]] static std::optional createFromFile(const std::filesystem::path& filename, - bool sRgb = false, - const IntRect& area = {}); - - //////////////////////////////////////////////////////////// - /// \brief Load the texture from a file in memory - /// - /// The \a area argument can be used to load only a sub-rectangle - /// of the whole image. If you want the entire image then leave - /// the default value (which is an empty IntRect). - /// If the \a area rectangle crosses the bounds of the image, it - /// is adjusted to fit the image size. - /// - /// The maximum size for a texture depends on the graphics - /// driver and can be retrieved with the getMaximumSize function. - /// - /// If this function fails, the texture is left unchanged. - /// - /// \param data Pointer to the file data in memory - /// \param size Size of the data to load, in bytes - /// \param sRgb True to enable sRGB conversion, false to disable it - /// \param area Area of the image to load - /// - /// \return Texture if loading was successful, otherwise `std::nullopt` - /// - /// \see createFromFile, createFromStream, createFromImage - /// - //////////////////////////////////////////////////////////// - [[nodiscard]] static std::optional createFromMemory( - const void* data, - std::size_t size, - bool sRgb = false, - const IntRect& area = {}); - - //////////////////////////////////////////////////////////// - /// \brief Load the texture from a custom stream - /// - /// The \a area argument can be used to load only a sub-rectangle - /// of the whole image. If you want the entire image then leave - /// the default value (which is an empty IntRect). - /// If the \a area rectangle crosses the bounds of the image, it - /// is adjusted to fit the image size. - /// - /// The maximum size for a texture depends on the graphics - /// driver and can be retrieved with the getMaximumSize function. - /// - /// If this function fails, the texture is left unchanged. - /// - /// \param stream Source stream to read from - /// \param sRgb True to enable sRGB conversion, false to disable it - /// \param area Area of the image to load - /// - /// \return Texture if loading was successful, otherwise `std::nullopt` - /// - /// \see createFromFile, createFromMemory, createFromImage - /// - //////////////////////////////////////////////////////////// - [[nodiscard]] static std::optional createFromStream(InputStream& stream, - bool sRgb = false, - const IntRect& area = {}); - - //////////////////////////////////////////////////////////// - /// \brief Load the texture from an image - /// - /// The \a area argument can be used to load only a sub-rectangle - /// of the whole image. If you want the entire image then leave - /// the default value (which is an empty IntRect). - /// If the \a area rectangle crosses the bounds of the image, it - /// is adjusted to fit the image size. - /// - /// The maximum size for a texture depends on the graphics - /// driver and can be retrieved with the getMaximumSize function. - /// - /// If this function fails, the texture is left unchanged. - /// - /// \param image Image to load into the texture - /// \param sRgb True to enable sRGB conversion, false to disable it - /// \param area Area of the image to load - /// - /// \return Texture if loading was successful, otherwise `std::nullopt` - /// - /// \see createFromFile, createFromMemory - /// - //////////////////////////////////////////////////////////// - [[nodiscard]] static std::optional 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 @@ public: /// /// \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 06644d17e..3d0cae96a 100644 --- a/include/SFML/System/FileInputStream.hpp +++ b/include/SFML/System/FileInputStream.hpp @@ -95,6 +95,16 @@ public: //////////////////////////////////////////////////////////// FileInputStream& operator=(FileInputStream&&) noexcept; + //////////////////////////////////////////////////////////// + /// \brief Construct the stream from a file path + /// + /// \param filename Name of the file to open + /// + /// \throws std::runtime_error on error + /// + //////////////////////////////////////////////////////////// + explicit FileInputStream(const std::filesystem::path& filename); + //////////////////////////////////////////////////////////// /// \brief Open the stream from a file path /// @@ -105,16 +115,6 @@ public: //////////////////////////////////////////////////////////// [[nodiscard]] bool open(const std::filesystem::path& filename); - //////////////////////////////////////////////////////////// - /// \brief Create the stream from a file path - /// - /// \param filename Name of the file to open - /// - /// \return File input stream on success, `std::nullopt` on error - /// - //////////////////////////////////////////////////////////// - [[nodiscard]] static std::optional create(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 19bc9e5a8..fa298e177 100644 --- a/include/SFML/System/InputStream.hpp +++ b/include/SFML/System/InputStream.hpp @@ -103,12 +103,12 @@ public: /// 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 @@ public: /// // 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 917a037e9..95a3fa925 100644 --- a/include/SFML/System/MemoryInputStream.hpp +++ b/include/SFML/System/MemoryInputStream.hpp @@ -55,15 +55,6 @@ public: //////////////////////////////////////////////////////////// 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 816cbda1b..6207ee24e 100644 --- a/include/SFML/Window/Cursor.hpp +++ b/include/SFML/Window/Cursor.hpp @@ -144,6 +144,55 @@ public: //////////////////////////////////////////////////////////// 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 2310c1125..0fa3e5cb0 100644 --- a/include/SFML/Window/Window.hpp +++ b/include/SFML/Window/Window.hpp @@ -89,7 +89,7 @@ public: 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 @@ public: /// \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 @@ public: /// \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 a6afcb79b..97714658b 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 970b1106f..572478338 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 2b18bad1c..eb3f59239 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 16501555f..6b6759e24 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 dbe02cbd8..48307e279 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 b26101e19..c6f9c6f12 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 ece5614d6..9d9e9228c 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 4b83d8689..f93b393b8 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 (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; - } + if (!m_impl) + return; - // Update the target texture - m_impl->updateTexture(m_texture.m_texture); - m_texture.m_pixelsFlipped = true; - m_texture.invalidateMipmap(); + 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(); } @@ -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 a801c093e..fff90a1de 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) + if (!m_shaderProgram) + return; + + const TransientContextLock lock; + + // Find the location of the variable in the shader + const int location = getUniformLocation(name); + if (location != -1) { - const TransientContextLock lock; - - // 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()) { - // 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; - } + 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; - } + 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); } @@ -1077,6 +1036,74 @@ int Shader::getUniformLocation(const std::string& name) namespace sf { +//////////////////////////////////////////////////////////// +Shader::Shader(const std::filesystem::path& /* filename */, Type /* type */) +{ + throw std::runtime_error("Shaders are not supported with OpenGL ES 1"); +} + + +//////////////////////////////////////////////////////////// +Shader::Shader(const std::filesystem::path& /* vertexShaderFilename */, + const std::filesystem::path& /* fragmentShaderFilename */) +{ + throw std::runtime_error("Shaders are not supported with OpenGL ES 1"); +} + + +//////////////////////////////////////////////////////////// +Shader::Shader(const std::filesystem::path& /* vertexShaderFilename */, + const std::filesystem::path& /* geometryShaderFilename */, + const std::filesystem::path& /* fragmentShaderFilename */) +{ + throw std::runtime_error("Shaders are not supported with OpenGL ES 1"); +} + + +//////////////////////////////////////////////////////////// +Shader::Shader(std::string_view /* shader */, Type /* type */) +{ + throw std::runtime_error("Shaders are not supported with OpenGL ES 1"); +} + + +//////////////////////////////////////////////////////////// +Shader::Shader(std::string_view /* vertexShader */, std::string_view /* fragmentShader */) +{ + throw std::runtime_error("Shaders are not supported with OpenGL ES 1"); +} + + +//////////////////////////////////////////////////////////// +Shader::Shader(std::string_view /* vertexShader */, std::string_view /* geometryShader */, std::string_view /* fragmentShader */) +{ + throw std::runtime_error("Shaders are not supported with OpenGL ES 1"); +} + + +//////////////////////////////////////////////////////////// +Shader::Shader(InputStream& /* stream */, Type /* type */) +{ + throw std::runtime_error("Shaders are not supported with OpenGL ES 1"); +} + + +//////////////////////////////////////////////////////////// +Shader::Shader(InputStream& /* vertexShaderStream */, InputStream& /* fragmentShaderStream */) +{ + throw std::runtime_error("Shaders are not supported with OpenGL ES 1"); +} + + +//////////////////////////////////////////////////////////// +Shader::Shader(InputStream& /* vertexShaderStream */, + InputStream& /* geometryShaderStream */, + InputStream& /* fragmentShaderStream */) +{ + throw std::runtime_error("Shaders are not supported with OpenGL ES 1"); +} + + //////////////////////////////////////////////////////////// Shader::~Shader() = default; @@ -1159,76 +1186,6 @@ bool Shader::loadFromStream(InputStream& /* vertexShaderStream */, } -//////////////////////////////////////////////////////////// -std::optional Shader::createFromFile(const std::filesystem::path& /* filename */, Type /* type */) -{ - return std::nullopt; -} - - -//////////////////////////////////////////////////////////// -std::optional Shader::createFromFile(const std::filesystem::path& /* vertexShaderFilename */, - const std::filesystem::path& /* fragmentShaderFilename */) -{ - return std::nullopt; -} - - -//////////////////////////////////////////////////////////// -std::optional Shader::createFromFile(const std::filesystem::path& /* vertexShaderFilename */, - const std::filesystem::path& /* geometryShaderFilename */, - const std::filesystem::path& /* fragmentShaderFilename */) -{ - return std::nullopt; -} - - -//////////////////////////////////////////////////////////// -std::optional Shader::createFromMemory(std::string_view /* shader */, Type /* type */) -{ - return std::nullopt; -} - - -//////////////////////////////////////////////////////////// -std::optional Shader::createFromMemory(std::string_view /* vertexShader */, std::string_view /* fragmentShader */) -{ - return std::nullopt; -} - - -//////////////////////////////////////////////////////////// -std::optional Shader::createFromMemory(std::string_view /* vertexShader */, - std::string_view /* geometryShader */, - std::string_view /* fragmentShader */) -{ - return std::nullopt; -} - - -//////////////////////////////////////////////////////////// -std::optional Shader::createFromStream(InputStream& /* stream */, Type /* type */) -{ - return std::nullopt; -} - - -//////////////////////////////////////////////////////////// -std::optional Shader::createFromStream(InputStream& /* vertexShaderStream */, InputStream& /* fragmentShaderStream */) -{ - return std::nullopt; -} - - -//////////////////////////////////////////////////////////// -std::optional Shader::createFromStream(InputStream& /* vertexShaderStream */, - InputStream& /* geometryShaderStream */, - InputStream& /* fragmentShaderStream */) -{ - return std::nullopt; -} - - //////////////////////////////////////////////////////////// void Shader::setUniform(const std::string& /* name */, float) { diff --git a/src/SFML/Graphics/Texture.cpp b/src/SFML/Graphics/Texture.cpp index 45661ae87..125143970 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 df075a662..83809cd8f 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 56dec3b4e..edec0eb5a 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 97fd9b30c..4ced9472d 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 376c6d308..ead0e8a50 100644 --- a/test/Audio/InputSoundFile.test.cpp +++ b/test/Audio/InputSoundFile.test.cpp @@ -23,13 +23,131 @@ 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("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_THROWS_AS(sf::InputSoundFile("does/not/exist.wav"), std::runtime_error); + } + + SECTION("Valid file") + { + SECTION("flac") + { + const sf::InputSoundFile inputSoundFile("Audio/ding.flac"); + CHECK(inputSoundFile.getSampleCount() == 87'798); + CHECK(inputSoundFile.getChannelCount() == 1); + CHECK(inputSoundFile.getSampleRate() == 44'100); + CHECK(inputSoundFile.getDuration() == sf::microseconds(1'990'884)); + CHECK(inputSoundFile.getTimeOffset() == sf::Time::Zero); + CHECK(inputSoundFile.getSampleOffset() == 0); + } + + SECTION("mp3") + { + const sf::InputSoundFile inputSoundFile("Audio/ding.mp3"); + CHECK(inputSoundFile.getSampleCount() == 87'798); + CHECK(inputSoundFile.getChannelCount() == 1); + CHECK(inputSoundFile.getSampleRate() == 44'100); + CHECK(inputSoundFile.getDuration() == sf::microseconds(1'990'884)); + CHECK(inputSoundFile.getTimeOffset() == sf::Time::Zero); + CHECK(inputSoundFile.getSampleOffset() == 0); + } + + SECTION("ogg") + { + const sf::InputSoundFile inputSoundFile("Audio/doodle_pop.ogg"); + CHECK(inputSoundFile.getSampleCount() == 2'116'992); + CHECK(inputSoundFile.getChannelCount() == 2); + CHECK(inputSoundFile.getSampleRate() == 44'100); + CHECK(inputSoundFile.getDuration() == sf::microseconds(24'002'176)); + CHECK(inputSoundFile.getTimeOffset() == sf::Time::Zero); + CHECK(inputSoundFile.getSampleOffset() == 0); + } + + SECTION("wav") + { + const sf::InputSoundFile inputSoundFile("Audio/killdeer.wav"); + CHECK(inputSoundFile.getSampleCount() == 112'941); + CHECK(inputSoundFile.getChannelCount() == 1); + CHECK(inputSoundFile.getSampleRate() == 22'050); + CHECK(inputSoundFile.getDuration() == sf::microseconds(5'122'040)); + CHECK(inputSoundFile.getTimeOffset() == sf::Time::Zero); + CHECK(inputSoundFile.getSampleOffset() == 0); + } + } + + SECTION("Memory") + { + const auto memory = loadIntoMemory("Audio/killdeer.wav"); + const sf::InputSoundFile inputSoundFile(memory.data(), memory.size()); + CHECK(inputSoundFile.getSampleCount() == 112'941); + CHECK(inputSoundFile.getChannelCount() == 1); + CHECK(inputSoundFile.getSampleRate() == 22'050); + CHECK(inputSoundFile.getDuration() == sf::microseconds(5'122'040)); + CHECK(inputSoundFile.getTimeOffset() == sf::Time::Zero); + CHECK(inputSoundFile.getSampleOffset() == 0); + } + + SECTION("Stream") + { + SECTION("flac") + { + sf::FileInputStream stream("Audio/ding.flac"); + const sf::InputSoundFile inputSoundFile(stream); + CHECK(inputSoundFile.getSampleCount() == 87'798); + CHECK(inputSoundFile.getChannelCount() == 1); + CHECK(inputSoundFile.getSampleRate() == 44'100); + CHECK(inputSoundFile.getDuration() == sf::microseconds(1'990'884)); + CHECK(inputSoundFile.getTimeOffset() == sf::Time::Zero); + CHECK(inputSoundFile.getSampleOffset() == 0); + } + + SECTION("mp3") + { + sf::FileInputStream stream("Audio/ding.mp3"); + const sf::InputSoundFile inputSoundFile(stream); + CHECK(inputSoundFile.getSampleCount() == 87'798); + CHECK(inputSoundFile.getChannelCount() == 1); + CHECK(inputSoundFile.getSampleRate() == 44'100); + CHECK(inputSoundFile.getDuration() == sf::microseconds(1'990'884)); + CHECK(inputSoundFile.getTimeOffset() == sf::Time::Zero); + CHECK(inputSoundFile.getSampleOffset() == 0); + } + + SECTION("ogg") + { + sf::FileInputStream stream("Audio/doodle_pop.ogg"); + const sf::InputSoundFile inputSoundFile(stream); + CHECK(inputSoundFile.getSampleCount() == 2'116'992); + CHECK(inputSoundFile.getChannelCount() == 2); + CHECK(inputSoundFile.getSampleRate() == 44'100); + CHECK(inputSoundFile.getDuration() == sf::microseconds(24'002'176)); + CHECK(inputSoundFile.getTimeOffset() == sf::Time::Zero); + CHECK(inputSoundFile.getSampleOffset() == 0); + } + + SECTION("wav") + { + sf::FileInputStream stream("Audio/killdeer.wav"); + const sf::InputSoundFile inputSoundFile(stream); + CHECK(inputSoundFile.getSampleCount() == 112'941); + CHECK(inputSoundFile.getChannelCount() == 1); + CHECK(inputSoundFile.getSampleRate() == 22'050); + CHECK(inputSoundFile.getDuration() == sf::microseconds(5'122'040)); + CHECK(inputSoundFile.getTimeOffset() == sf::Time::Zero); + CHECK(inputSoundFile.getSampleOffset() == 0); + } + } } SECTION("openFromFile()") @@ -164,129 +282,11 @@ TEST_CASE("[Audio] sf::InputSoundFile") } } - SECTION("createFromFile()") - { - SECTION("Invalid file") - { - CHECK(!sf::InputSoundFile::createFromFile("does/not/exist.wav")); - } - - SECTION("Valid file") - { - SECTION("flac") - { - const auto inputSoundFile = sf::InputSoundFile::createFromFile("Audio/ding.flac").value(); - CHECK(inputSoundFile.getSampleCount() == 87'798); - CHECK(inputSoundFile.getChannelCount() == 1); - CHECK(inputSoundFile.getSampleRate() == 44'100); - CHECK(inputSoundFile.getDuration() == sf::microseconds(1'990'884)); - CHECK(inputSoundFile.getTimeOffset() == sf::Time::Zero); - CHECK(inputSoundFile.getSampleOffset() == 0); - } - - SECTION("mp3") - { - const auto inputSoundFile = sf::InputSoundFile::createFromFile("Audio/ding.mp3").value(); - CHECK(inputSoundFile.getSampleCount() == 87'798); - CHECK(inputSoundFile.getChannelCount() == 1); - CHECK(inputSoundFile.getSampleRate() == 44'100); - CHECK(inputSoundFile.getDuration() == sf::microseconds(1'990'884)); - CHECK(inputSoundFile.getTimeOffset() == sf::Time::Zero); - CHECK(inputSoundFile.getSampleOffset() == 0); - } - - SECTION("ogg") - { - const auto inputSoundFile = sf::InputSoundFile::createFromFile("Audio/doodle_pop.ogg").value(); - CHECK(inputSoundFile.getSampleCount() == 2'116'992); - CHECK(inputSoundFile.getChannelCount() == 2); - CHECK(inputSoundFile.getSampleRate() == 44'100); - CHECK(inputSoundFile.getDuration() == sf::microseconds(24'002'176)); - CHECK(inputSoundFile.getTimeOffset() == sf::Time::Zero); - CHECK(inputSoundFile.getSampleOffset() == 0); - } - - SECTION("wav") - { - const auto inputSoundFile = sf::InputSoundFile::createFromFile("Audio/killdeer.wav").value(); - CHECK(inputSoundFile.getSampleCount() == 112'941); - CHECK(inputSoundFile.getChannelCount() == 1); - CHECK(inputSoundFile.getSampleRate() == 22'050); - CHECK(inputSoundFile.getDuration() == sf::microseconds(5'122'040)); - CHECK(inputSoundFile.getTimeOffset() == sf::Time::Zero); - CHECK(inputSoundFile.getSampleOffset() == 0); - } - } - } - - SECTION("createFromMemory()") - { - const auto memory = loadIntoMemory("Audio/killdeer.wav"); - const auto inputSoundFile = sf::InputSoundFile::createFromMemory(memory.data(), memory.size()).value(); - CHECK(inputSoundFile.getSampleCount() == 112'941); - CHECK(inputSoundFile.getChannelCount() == 1); - CHECK(inputSoundFile.getSampleRate() == 22'050); - CHECK(inputSoundFile.getDuration() == sf::microseconds(5'122'040)); - CHECK(inputSoundFile.getTimeOffset() == sf::Time::Zero); - CHECK(inputSoundFile.getSampleOffset() == 0); - } - - SECTION("createFromStream()") - { - SECTION("flac") - { - auto stream = sf::FileInputStream::create("Audio/ding.flac").value(); - const auto inputSoundFile = sf::InputSoundFile::createFromStream(stream).value(); - CHECK(inputSoundFile.getSampleCount() == 87'798); - CHECK(inputSoundFile.getChannelCount() == 1); - CHECK(inputSoundFile.getSampleRate() == 44'100); - CHECK(inputSoundFile.getDuration() == sf::microseconds(1'990'884)); - CHECK(inputSoundFile.getTimeOffset() == sf::Time::Zero); - CHECK(inputSoundFile.getSampleOffset() == 0); - } - - SECTION("mp3") - { - auto stream = sf::FileInputStream::create("Audio/ding.mp3").value(); - const auto inputSoundFile = sf::InputSoundFile::createFromStream(stream).value(); - CHECK(inputSoundFile.getSampleCount() == 87'798); - CHECK(inputSoundFile.getChannelCount() == 1); - CHECK(inputSoundFile.getSampleRate() == 44'100); - CHECK(inputSoundFile.getDuration() == sf::microseconds(1'990'884)); - CHECK(inputSoundFile.getTimeOffset() == sf::Time::Zero); - CHECK(inputSoundFile.getSampleOffset() == 0); - } - - SECTION("ogg") - { - auto stream = sf::FileInputStream::create("Audio/doodle_pop.ogg").value(); - const auto inputSoundFile = sf::InputSoundFile::createFromStream(stream).value(); - CHECK(inputSoundFile.getSampleCount() == 2'116'992); - CHECK(inputSoundFile.getChannelCount() == 2); - CHECK(inputSoundFile.getSampleRate() == 44'100); - CHECK(inputSoundFile.getDuration() == sf::microseconds(24'002'176)); - CHECK(inputSoundFile.getTimeOffset() == sf::Time::Zero); - CHECK(inputSoundFile.getSampleOffset() == 0); - } - - SECTION("wav") - { - auto stream = sf::FileInputStream::create("Audio/killdeer.wav").value(); - const auto inputSoundFile = sf::InputSoundFile::createFromStream(stream).value(); - CHECK(inputSoundFile.getSampleCount() == 112'941); - CHECK(inputSoundFile.getChannelCount() == 1); - CHECK(inputSoundFile.getSampleRate() == 22'050); - CHECK(inputSoundFile.getDuration() == sf::microseconds(5'122'040)); - CHECK(inputSoundFile.getTimeOffset() == sf::Time::Zero); - CHECK(inputSoundFile.getSampleOffset() == 0); - } - } - SECTION("seek(std::uint64_t)") { SECTION("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 5d7aa38c7..fede6b645 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 765e79ddd..b1aee5d5f 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 70717f0c5..1b156c2a8 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 94cb0c971..aae378ebf 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 2b8d6e0a2..5d797657c 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 3dafc19ca..4b9521995 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 2f017abc5..fef5e7163 100644 --- a/test/Graphics/Font.test.cpp +++ b/test/Graphics/Font.test.cpp @@ -23,13 +23,114 @@ 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("Default constructor") + { + 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("File") + { + SECTION("Invalid filename") + { + CHECK_THROWS_AS(sf::Font("does/not/exist.ttf"), std::runtime_error); + } + + SECTION("Successful load") + { + const sf::Font font("Graphics/tuffy.ttf"); + CHECK(font.getInfo().family == "Tuffy"); + const auto& glyph = font.getGlyph(0x45, 16, false); + CHECK(glyph.advance == 9); + CHECK(glyph.lsbDelta == 9); + CHECK(glyph.rsbDelta == 16); + CHECK(glyph.bounds == sf::FloatRect({0, -12}, {8, 12})); + CHECK(glyph.textureRect == sf::IntRect({2, 5}, {8, 12})); + CHECK(font.hasGlyph(0x41)); + CHECK(font.hasGlyph(0xC0)); + CHECK(font.getKerning(0x41, 0x42, 12) == -1); + CHECK(font.getKerning(0x43, 0x44, 24, true) == 0); + CHECK(font.getLineSpacing(24) == 30); + CHECK(font.getUnderlinePosition(36) == Approx(2.20312f)); + CHECK(font.getUnderlineThickness(48) == Approx(1.17188f)); + const auto& texture = font.getTexture(10); + CHECK(texture.getSize() == sf::Vector2u(128, 128)); + CHECK(texture.isSmooth()); + CHECK(!texture.isSrgb()); + CHECK(!texture.isRepeated()); + CHECK(texture.getNativeHandle() != 0); + CHECK(font.isSmooth()); + } + } + + SECTION("Memory") + { + SECTION("Invalid data and size") + { + CHECK_THROWS_AS(sf::Font(nullptr, 1), std::runtime_error); + const std::byte testByte{0xCD}; + CHECK_THROWS_AS(sf::Font(&testByte, 0), std::runtime_error); + } + + SECTION("Successful load") + { + const auto memory = loadIntoMemory("Graphics/tuffy.ttf"); + const sf::Font font(memory.data(), memory.size()); + CHECK(font.getInfo().family == "Tuffy"); + const auto& glyph = font.getGlyph(0x45, 16, false); + CHECK(glyph.advance == 9); + CHECK(glyph.lsbDelta == 9); + CHECK(glyph.rsbDelta == 16); + CHECK(glyph.bounds == sf::FloatRect({0, -12}, {8, 12})); + CHECK(glyph.textureRect == sf::IntRect({2, 5}, {8, 12})); + CHECK(font.hasGlyph(0x41)); + CHECK(font.hasGlyph(0xC0)); + CHECK(font.getKerning(0x41, 0x42, 12) == -1); + CHECK(font.getKerning(0x43, 0x44, 24, true) == 0); + CHECK(font.getLineSpacing(24) == 30); + CHECK(font.getUnderlinePosition(36) == Approx(2.20312f)); + CHECK(font.getUnderlineThickness(48) == Approx(1.17188f)); + const auto& texture = font.getTexture(10); + CHECK(texture.getSize() == sf::Vector2u(128, 128)); + CHECK(texture.isSmooth()); + CHECK(!texture.isSrgb()); + CHECK(!texture.isRepeated()); + CHECK(texture.getNativeHandle() != 0); + CHECK(font.isSmooth()); + } + } + + SECTION("Stream") + { + sf::FileInputStream stream("Graphics/tuffy.ttf"); + const sf::Font font(stream); + CHECK(font.getInfo().family == "Tuffy"); + const auto& glyph = font.getGlyph(0x45, 16, false); + CHECK(glyph.advance == 9); + CHECK(glyph.lsbDelta == 9); + CHECK(glyph.rsbDelta == 16); + CHECK(glyph.bounds == sf::FloatRect({0, -12}, {8, 12})); + CHECK(glyph.textureRect == sf::IntRect({2, 5}, {8, 12})); + CHECK(font.hasGlyph(0x41)); + CHECK(font.hasGlyph(0xC0)); + CHECK(font.getKerning(0x41, 0x42, 12) == -1); + CHECK(font.getKerning(0x43, 0x44, 24, true) == 0); + CHECK(font.getLineSpacing(24) == 30); + CHECK(font.getUnderlinePosition(36) == Approx(2.20312f)); + CHECK(font.getUnderlineThickness(48) == Approx(1.17188f)); + const auto& texture = font.getTexture(10); + CHECK(texture.getSize() == sf::Vector2u(128, 128)); + CHECK(texture.isSmooth()); + CHECK(!texture.isSrgb()); + CHECK(!texture.isRepeated()); + CHECK(texture.getNativeHandle() != 0); + CHECK(font.isSmooth()); + } } SECTION("openFromFile()") @@ -145,107 +246,9 @@ TEST_CASE("[Graphics] sf::Font", runDisplayTests()) } } - SECTION("createFromFile()") - { - SECTION("Invalid filename") - { - CHECK(!sf::Font::createFromFile("does/not/exist.ttf")); - } - - SECTION("Valid file") - { - const auto font = sf::Font::createFromFile("Graphics/tuffy.ttf").value(); - CHECK(font.getInfo().family == "Tuffy"); - const auto& glyph = font.getGlyph(0x45, 16, false); - CHECK(glyph.advance == 9); - CHECK(glyph.lsbDelta == 9); - CHECK(glyph.rsbDelta == 16); - CHECK(glyph.bounds == sf::FloatRect({0, -12}, {8, 12})); - CHECK(glyph.textureRect == sf::IntRect({2, 5}, {8, 12})); - CHECK(font.hasGlyph(0x41)); - CHECK(font.hasGlyph(0xC0)); - CHECK(font.getKerning(0x41, 0x42, 12) == -1); - CHECK(font.getKerning(0x43, 0x44, 24, true) == 0); - CHECK(font.getLineSpacing(24) == 30); - CHECK(font.getUnderlinePosition(36) == Approx(2.20312f)); - CHECK(font.getUnderlineThickness(48) == Approx(1.17188f)); - const auto& texture = font.getTexture(10); - CHECK(texture.getSize() == sf::Vector2u(128, 128)); - CHECK(texture.isSmooth()); - CHECK(!texture.isSrgb()); - CHECK(!texture.isRepeated()); - CHECK(texture.getNativeHandle() != 0); - CHECK(font.isSmooth()); - } - } - - SECTION("createFromMemory()") - { - SECTION("Invalid data and size") - { - CHECK(!sf::Font::createFromMemory(nullptr, 1)); - const std::byte testByte{0xCD}; - CHECK(!sf::Font::createFromMemory(&testByte, 0)); - } - - SECTION("Valid data") - { - const auto memory = loadIntoMemory("Graphics/tuffy.ttf"); - const auto font = sf::Font::createFromMemory(memory.data(), memory.size()).value(); - CHECK(font.getInfo().family == "Tuffy"); - const auto& glyph = font.getGlyph(0x45, 16, false); - CHECK(glyph.advance == 9); - CHECK(glyph.lsbDelta == 9); - CHECK(glyph.rsbDelta == 16); - CHECK(glyph.bounds == sf::FloatRect({0, -12}, {8, 12})); - CHECK(glyph.textureRect == sf::IntRect({2, 5}, {8, 12})); - CHECK(font.hasGlyph(0x41)); - CHECK(font.hasGlyph(0xC0)); - CHECK(font.getKerning(0x41, 0x42, 12) == -1); - CHECK(font.getKerning(0x43, 0x44, 24, true) == 0); - CHECK(font.getLineSpacing(24) == 30); - CHECK(font.getUnderlinePosition(36) == Approx(2.20312f)); - CHECK(font.getUnderlineThickness(48) == Approx(1.17188f)); - const auto& texture = font.getTexture(10); - CHECK(texture.getSize() == sf::Vector2u(128, 128)); - CHECK(texture.isSmooth()); - CHECK(!texture.isSrgb()); - CHECK(!texture.isRepeated()); - CHECK(texture.getNativeHandle() != 0); - CHECK(font.isSmooth()); - } - } - - SECTION("createFromStream()") - { - auto stream = sf::FileInputStream::create("Graphics/tuffy.ttf").value(); - const auto font = sf::Font::createFromStream(stream).value(); - CHECK(font.getInfo().family == "Tuffy"); - const auto& glyph = font.getGlyph(0x45, 16, false); - CHECK(glyph.advance == 9); - CHECK(glyph.lsbDelta == 9); - CHECK(glyph.rsbDelta == 16); - CHECK(glyph.bounds == sf::FloatRect({0, -12}, {8, 12})); - CHECK(glyph.textureRect == sf::IntRect({2, 5}, {8, 12})); - CHECK(font.hasGlyph(0x41)); - CHECK(font.hasGlyph(0xC0)); - CHECK(font.getKerning(0x41, 0x42, 12) == -1); - CHECK(font.getKerning(0x43, 0x44, 24, true) == 0); - CHECK(font.getLineSpacing(24) == 30); - CHECK(font.getUnderlinePosition(36) == Approx(2.20312f)); - CHECK(font.getUnderlineThickness(48) == Approx(1.17188f)); - const auto& texture = font.getTexture(10); - CHECK(texture.getSize() == sf::Vector2u(128, 128)); - CHECK(texture.isSmooth()); - CHECK(!texture.isSrgb()); - CHECK(!texture.isRepeated()); - CHECK(texture.getNativeHandle() != 0); - CHECK(font.isSmooth()); - } - SECTION("Set/get smooth") { - 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 851e7ab2d..f4857716d 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 28c9da10c..c01bf6860 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 bb2d718f6..c351c182e 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 d1cde4b71..e2ccbff8b 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 6405fd78e..5de640e73 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 1b577df8f..6a6399183 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 9d71b6ecd..bcde53110 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 c926c382c..ab1a38389 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 b4303329c..398bbf88b 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 777082ccb..dd0b2c864 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 e8ef66799..0beb47d46 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 f41e54a84..79bff581e 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 dac6a84db..f9ea74b82 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 045a00b79..3eaea6cf9 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