build system update

-sfml now downloads and builds from source automatically
-sfml now statically links on linux
This commit is contained in:
Joseph Aquino 2025-12-26 14:59:46 -05:00
parent e1e8c873e6
commit aaf6248870
149 changed files with 413 additions and 29142 deletions

4
.gitignore vendored
View File

@ -385,6 +385,10 @@ Makefile
*.ninja* *.ninja*
vendor/SFML/
.run/
.idea/ .idea/
Engine-Core/lib Engine-Core/lib

View File

@ -1,2 +1,3 @@
echo SFML will be downloaded and built from source, this may take a while depending on your system.
.\vendor\premake5\premake5.exe vs2022 .\vendor\premake5\premake5.exe vs2022
PAUSE PAUSE

View File

@ -1,4 +1,4 @@
#! /bin/bash #! /bin/bash
echo SFML will be downloaded and built from source, this may take a while depending on your system.
./vendor/premake5/premake5 ninja ./vendor/premake5/premake5 premake-ninja
ninja $1 ninja $1

View File

@ -1,4 +1,4 @@
#! /bin/bash #! /bin/bash
echo SFML will be downloaded and built from source, this may take a while depending on your system.
./vendor/premake5/premake5 gmake ./vendor/premake5/premake5 gmake
make config=$1 make config=$1

View File

@ -4,31 +4,67 @@ require "ninja/ninja"
workspace "snake" workspace "snake"
architecture "x64" architecture "x64"
output_dir = "%{cfg.buildcfg}-%{cfg.system}-%{cfg.architecture}"
vs_intdir = "!$(SolutionDir)intermediate-files/" .. output_dir
intdir = "%{wks.location}/intermediate-files/" .. output_dir
vs_bindir = "$(SolutionDir)bin/" .. output_dir
bindir = "%{wks.location}/bin/" .. output_dir
vs_coreinclude_dir = "$(SolutionDir)include"
vs_sfmldir = "$(SolutionDir)vendor/SFML"
sfmldir = "%{wks.location}/vendor/SFML"
vs_imguidir = "$(SolutionDir)vendor/imgui"
imguidir = "%{wks.location}/vendor/imgui"
vs_include_dir = "$(SolutionDir)include"
include_dir = "%{wks.location}/include"
configurations configurations
{ {
"Debug", "Debug",
"Release" "Release"
} }
prebuildcommands {
"git clone https://github.com/SFML/SFML.git vendor/SFML",
"cd vendor/SFML && git checkout 3.0.2",
}
filter "action:vs*"
prebuildcommands
{
"cd vendor/SFML && cmake -S . -B build -DCMAKE_BUILD_TYPE=Release -DBUILD_SHARED_LIBS=0 -DSFML_BUILD_AUDIO=1 -DSFML_BUILD_GRAPHICS=1 -DSFML_BUILD_WINDOW=1 -DSFML_USE_STATIC_STD_LIBS=1 -DCMAKE_LIBRARY_OUTPUT_DIRECTORY=./lib"
}
project_dir = "$(SolutionDir)"
filter "action:gmake"
prebuildcommands
{
"cd vendor/SFML && cmake -S . -B build -G \"Unix Makefiles\" -DCMAKE_BUILD_TYPE=Release -DBUILD_SHARED_LIBS=0 -DSFML_BUILD_AUDIO=1 -DSFML_BUILD_GRAPHICS=1 -DSFML_BUILD_WINDOW=1",
"cd vendor/SFML && cmake --build build"
}
project_dir = "%{wks.location}/"
filter "action:premake-ninja"
prebuildcommands
{
"cmake -S . -B build -G Ninja -DCMAKE_BUILD_TYPE=Release -DBUILD_SHARED_LIBS=0 -DSFML_BUILD_AUDIO=1 -DSFML_BUILD_GRAPHICS=1 -DSFML_BUILD_WINDOW=1",
"cmake --build build"
}
project_dir = "%{wks.location}/"
filter""
project "snake" project "snake"
output_dir = "%{cfg.buildcfg}-%{cfg.system}-%{cfg.architecture}"
intdir = project_dir .. "intermediate-files/" .. output_dir
bindir = project_dir .. "bin/" .. output_dir
sfmldir = project_dir .. "vendor/SFML"
imguidir = project_dir .. "vendor/imgui"
include_dir = project_dir .. "include"
language "C++" language "C++"
cppdialect "C++20" cppdialect "C++20"
systemversion "latest" systemversion "latest"
kind "WindowedApp" kind "WindowedApp"
targetname "snake" targetname "snake"
targetdir (bindir)
objdir (intdir)
debugdir (project_dir)
includedirs
{
"src",
include_dir,
sfmldir .. "/include",
imguidir
}
libdirs (sfmldir .. "/build/lib")
files files
{ {
@ -42,36 +78,6 @@ workspace "snake"
"vendor/imgui/imgui-SFML.cpp" "vendor/imgui/imgui-SFML.cpp"
} }
--visual studio--
filter {"action:vs*", "system:windows"}
targetdir (vs_bindir)
objdir (vs_intdir)
debugdir "$(SolutionDir)"
includedirs
{
"src",
vs_include_dir,
vs_sfmldir .. "/include",
vs_imguidir
}
libdirs {vs_sfmldir .."/lib"}
--not visual studio --
filter {"not action:vs*", "system:windows"}
targetdir (bindir)
objdir (intdir)
debugdir "%{wks.location}"
includedirs
{
"src",
include_dir,
sfmldir .. "/include",
imguidir
}
libdirs {sfmldir .."/lib"}
--windows specific settings-- --windows specific settings--
filter{"system:windows"} filter{"system:windows"}
defines {"PLATFORM_WINDOWS", "SFML_STATIC"} defines {"PLATFORM_WINDOWS", "SFML_STATIC"}
@ -119,22 +125,25 @@ workspace "snake"
--linux specific settings-- --linux specific settings--
filter {"system:linux"} filter {"system:linux"}
defines {"PLATFORM_LINUX"} defines {"PLATFORM_LINUX"}
targetdir (bindir)
objdir (intdir)
debugdir "%{wks.location}"
includedirs
{
"src",
include_dir,
imguidir
}
links links
{ {
"sfml-graphics", "sfml-graphics-s",
"sfml-window", "sfml-window-s",
"sfml-audio", "sfml-audio-s",
"sfml-system", "sfml-system-s",
"Xi",
"Xrandr",
"Xcursor",
"freetype",
"X11",
"udev",
"FLAC",
"ogg",
"vorbis",
"vorbisenc",
"vorbisfile",
"pthread",
"OpenGL", "OpenGL",
} }

View File

@ -1,55 +0,0 @@
////////////////////////////////////////////////////////////
//
// SFML - Simple and Fast Multimedia Library
// Copyright (C) 2007-2025 Laurent Gomila (laurent@sfml-dev.org)
//
// This software is provided 'as-is', without any express or implied warranty.
// In no event will the authors be held liable for any damages arising from the use of this software.
//
// Permission is granted to anyone to use this software for any purpose,
// including commercial applications, and to alter it and redistribute it freely,
// subject to the following restrictions:
//
// 1. The origin of this software must not be misrepresented;
// you must not claim that you wrote the original software.
// If you use this software in a product, an acknowledgment
// in the product documentation would be appreciated but is not required.
//
// 2. Altered source versions must be plainly marked as such,
// and must not be misrepresented as being the original software.
//
// 3. This notice may not be removed or altered from any source distribution.
//
////////////////////////////////////////////////////////////
#pragma once
////////////////////////////////////////////////////////////
// Headers
////////////////////////////////////////////////////////////
#include <SFML/Audio/InputSoundFile.hpp>
#include <SFML/Audio/Listener.hpp>
#include <SFML/Audio/Music.hpp>
#include <SFML/Audio/OutputSoundFile.hpp>
#include <SFML/Audio/PlaybackDevice.hpp>
#include <SFML/Audio/Sound.hpp>
#include <SFML/Audio/SoundBuffer.hpp>
#include <SFML/Audio/SoundBufferRecorder.hpp>
#include <SFML/Audio/SoundFileFactory.hpp>
#include <SFML/Audio/SoundFileReader.hpp>
#include <SFML/Audio/SoundFileWriter.hpp>
#include <SFML/Audio/SoundRecorder.hpp>
#include <SFML/Audio/SoundSource.hpp>
#include <SFML/Audio/SoundStream.hpp>
#include <SFML/System.hpp>
////////////////////////////////////////////////////////////
/// \defgroup audio Audio module
///
/// Sounds, streaming (musics or custom sources), recording,
/// spatialization.
///
////////////////////////////////////////////////////////////

View File

@ -1,93 +0,0 @@
////////////////////////////////////////////////////////////
//
// SFML - Simple and Fast Multimedia Library
// Copyright (C) 2007-2025 Laurent Gomila (laurent@sfml-dev.org)
//
// This software is provided 'as-is', without any express or implied warranty.
// In no event will the authors be held liable for any damages arising from the use of this software.
//
// Permission is granted to anyone to use this software for any purpose,
// including commercial applications, and to alter it and redistribute it freely,
// subject to the following restrictions:
//
// 1. The origin of this software must not be misrepresented;
// you must not claim that you wrote the original software.
// If you use this software in a product, an acknowledgment
// in the product documentation would be appreciated but is not required.
//
// 2. Altered source versions must be plainly marked as such,
// and must not be misrepresented as being the original software.
//
// 3. This notice may not be removed or altered from any source distribution.
//
////////////////////////////////////////////////////////////
#pragma once
////////////////////////////////////////////////////////////
// Headers
////////////////////////////////////////////////////////////
#include <SFML/Audio/Export.hpp>
#include <memory>
namespace sf
{
////////////////////////////////////////////////////////////
/// \brief Base class for classes that require an audio device
///
////////////////////////////////////////////////////////////
class SFML_AUDIO_API AudioResource
{
public:
////////////////////////////////////////////////////////////
/// \brief Copy constructor
///
////////////////////////////////////////////////////////////
AudioResource(const AudioResource&) = default;
////////////////////////////////////////////////////////////
/// \brief Copy assignment
///
////////////////////////////////////////////////////////////
AudioResource& operator=(const AudioResource&) = default;
////////////////////////////////////////////////////////////
/// \brief Move constructor
///
////////////////////////////////////////////////////////////
AudioResource(AudioResource&&) noexcept = default;
////////////////////////////////////////////////////////////
/// \brief Move assignment
///
////////////////////////////////////////////////////////////
AudioResource& operator=(AudioResource&&) noexcept = default;
protected:
////////////////////////////////////////////////////////////
/// \brief Default constructor
///
////////////////////////////////////////////////////////////
AudioResource();
private:
////////////////////////////////////////////////////////////
// Member data
////////////////////////////////////////////////////////////
std::shared_ptr<void> m_device; //!< Sound device
};
} // namespace sf
////////////////////////////////////////////////////////////
/// \class sf::AudioResource
/// \ingroup audio
///
/// This class is for internal use only, it must be the base
/// of every class that requires a valid audio device in
/// order to work.
///
////////////////////////////////////////////////////////////

View File

@ -1,44 +0,0 @@
////////////////////////////////////////////////////////////
//
// SFML - Simple and Fast Multimedia Library
// Copyright (C) 2007-2025 Laurent Gomila (laurent@sfml-dev.org)
//
// This software is provided 'as-is', without any express or implied warranty.
// In no event will the authors be held liable for any damages arising from the use of this software.
//
// Permission is granted to anyone to use this software for any purpose,
// including commercial applications, and to alter it and redistribute it freely,
// subject to the following restrictions:
//
// 1. The origin of this software must not be misrepresented;
// you must not claim that you wrote the original software.
// If you use this software in a product, an acknowledgment
// in the product documentation would be appreciated but is not required.
//
// 2. Altered source versions must be plainly marked as such,
// and must not be misrepresented as being the original software.
//
// 3. This notice may not be removed or altered from any source distribution.
//
////////////////////////////////////////////////////////////
#pragma once
////////////////////////////////////////////////////////////
// Headers
////////////////////////////////////////////////////////////
#include <SFML/Config.hpp>
////////////////////////////////////////////////////////////
// Portable import / export macros
////////////////////////////////////////////////////////////
#if defined(SFML_AUDIO_EXPORTS)
#define SFML_AUDIO_API SFML_API_EXPORT
#else
#define SFML_AUDIO_API SFML_API_IMPORT
#endif

View File

@ -1,336 +0,0 @@
////////////////////////////////////////////////////////////
//
// SFML - Simple and Fast Multimedia Library
// Copyright (C) 2007-2025 Laurent Gomila (laurent@sfml-dev.org)
//
// This software is provided 'as-is', without any express or implied warranty.
// In no event will the authors be held liable for any damages arising from the use of this software.
//
// Permission is granted to anyone to use this software for any purpose,
// including commercial applications, and to alter it and redistribute it freely,
// subject to the following restrictions:
//
// 1. The origin of this software must not be misrepresented;
// you must not claim that you wrote the original software.
// If you use this software in a product, an acknowledgment
// in the product documentation would be appreciated but is not required.
//
// 2. Altered source versions must be plainly marked as such,
// and must not be misrepresented as being the original software.
//
// 3. This notice may not be removed or altered from any source distribution.
//
////////////////////////////////////////////////////////////
#pragma once
////////////////////////////////////////////////////////////
// Headers
////////////////////////////////////////////////////////////
#include <SFML/Audio/Export.hpp>
#include <SFML/Audio/SoundFileReader.hpp>
#include <filesystem>
#include <memory>
#include <vector>
#include <cstddef>
#include <cstdint>
namespace sf
{
class Time;
class InputStream;
////////////////////////////////////////////////////////////
/// \brief Provide read access to sound files
///
////////////////////////////////////////////////////////////
class SFML_AUDIO_API InputSoundFile
{
public:
////////////////////////////////////////////////////////////
/// \brief Default constructor
///
/// Construct an input sound file that is not associated
/// with a file to read.
///
////////////////////////////////////////////////////////////
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 sf::Exception if opening the file was unsuccessful
///
////////////////////////////////////////////////////////////
explicit 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 sf::Exception 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 sf::Exception if opening the file was unsuccessful
///
////////////////////////////////////////////////////////////
explicit InputSoundFile(InputStream& stream);
////////////////////////////////////////////////////////////
/// \brief Open a sound file from the disk for reading
///
/// The supported audio formats are: WAV (PCM only), OGG/Vorbis, FLAC, MP3.
/// The supported sample sizes for FLAC and WAV are 8, 16, 24 and 32 bit.
///
/// 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 `true` if the file was successfully opened
///
////////////////////////////////////////////////////////////
[[nodiscard]] bool openFromFile(const std::filesystem::path& filename);
////////////////////////////////////////////////////////////
/// \brief Open a sound file in memory for reading
///
/// The supported audio formats are: WAV (PCM only), OGG/Vorbis, FLAC.
/// The supported sample sizes for FLAC and WAV are 8, 16, 24 and 32 bit.
///
/// \param data Pointer to the file data in memory
/// \param sizeInBytes Size of the data to load, in bytes
///
/// \return `true` if the file was successfully opened
///
////////////////////////////////////////////////////////////
[[nodiscard]] bool openFromMemory(const void* data, std::size_t sizeInBytes);
////////////////////////////////////////////////////////////
/// \brief Open a sound file from a custom stream for reading
///
/// The supported audio formats are: WAV (PCM only), OGG/Vorbis, FLAC.
/// The supported sample sizes for FLAC and WAV are 8, 16, 24 and 32 bit.
///
/// \param stream Source stream to read from
///
/// \return `true` if the file was successfully opened
///
////////////////////////////////////////////////////////////
[[nodiscard]] bool openFromStream(InputStream& stream);
////////////////////////////////////////////////////////////
/// \brief Get the total number of audio samples in the file
///
/// \return Number of samples
///
////////////////////////////////////////////////////////////
[[nodiscard]] std::uint64_t getSampleCount() const;
////////////////////////////////////////////////////////////
/// \brief Get the number of channels used by the sound
///
/// \return Number of channels (1 = mono, 2 = stereo)
///
////////////////////////////////////////////////////////////
[[nodiscard]] unsigned int getChannelCount() const;
////////////////////////////////////////////////////////////
/// \brief Get the sample rate of the sound
///
/// \return Sample rate, in samples per second
///
////////////////////////////////////////////////////////////
[[nodiscard]] unsigned int getSampleRate() const;
////////////////////////////////////////////////////////////
/// \brief Get the map of position in sample frame to sound channel
///
/// This is used to map a sample in the sample stream to a
/// position during spatialization.
///
/// \return Map of position in sample frame to sound channel
///
/// \see `getSampleRate`, `getChannelCount`, `getDuration`
///
////////////////////////////////////////////////////////////
[[nodiscard]] const std::vector<SoundChannel>& getChannelMap() const;
////////////////////////////////////////////////////////////
/// \brief Get the total duration of the sound file
///
/// This function is provided for convenience, the duration is
/// deduced from the other sound file attributes.
///
/// \return Duration of the sound file
///
////////////////////////////////////////////////////////////
[[nodiscard]] Time getDuration() const;
////////////////////////////////////////////////////////////
/// \brief Get the read offset of the file in time
///
/// \return Time position
///
////////////////////////////////////////////////////////////
[[nodiscard]] Time getTimeOffset() const;
////////////////////////////////////////////////////////////
/// \brief Get the read offset of the file in samples
///
/// \return Sample position
///
////////////////////////////////////////////////////////////
[[nodiscard]] std::uint64_t getSampleOffset() const;
////////////////////////////////////////////////////////////
/// \brief Change the current read position to the given sample offset
///
/// This function takes a sample offset to provide maximum
/// precision. If you need to jump to a given time, use the
/// other overload.
///
/// The sample offset takes the channels into account.
/// If you have a time offset instead, you can easily find
/// the corresponding sample offset with the following formula:
/// `timeInSeconds * sampleRate * channelCount`
/// If the given offset exceeds to total number of samples,
/// this function jumps to the end of the sound file.
///
/// \param sampleOffset Index of the sample to jump to, relative to the beginning
///
////////////////////////////////////////////////////////////
void seek(std::uint64_t sampleOffset);
////////////////////////////////////////////////////////////
/// \brief Change the current read position to the given time offset
///
/// Using a time offset is handy but imprecise. If you need an accurate
/// result, consider using the overload which takes a sample offset.
///
/// If the given time exceeds to total duration, this function jumps
/// to the end of the sound file.
///
/// \param timeOffset Time to jump to, relative to the beginning
///
////////////////////////////////////////////////////////////
void seek(Time timeOffset);
////////////////////////////////////////////////////////////
/// \brief Read audio samples from the open file
///
/// \param samples Pointer to the sample array to fill
/// \param maxCount Maximum number of samples to read
///
/// \return Number of samples actually read (may be less than \a maxCount)
///
////////////////////////////////////////////////////////////
[[nodiscard]] std::uint64_t read(std::int16_t* samples, std::uint64_t maxCount);
////////////////////////////////////////////////////////////
/// \brief Close the current file
///
////////////////////////////////////////////////////////////
void close();
private:
////////////////////////////////////////////////////////////
/// \brief Deleter for input streams that only conditionally deletes
///
////////////////////////////////////////////////////////////
struct SFML_AUDIO_API StreamDeleter
{
StreamDeleter(bool theOwned);
// To accept ownership transfer from usual std::unique_ptr<T>
template <typename T>
StreamDeleter(const std::default_delete<T>&);
void operator()(InputStream* ptr) const;
bool owned{true};
};
////////////////////////////////////////////////////////////
// Member data
////////////////////////////////////////////////////////////
std::unique_ptr<SoundFileReader> m_reader; //!< Reader that handles I/O on the file's format
std::unique_ptr<InputStream, StreamDeleter> m_stream{nullptr, false}; //!< Input stream used to access the file's data
std::uint64_t m_sampleOffset{}; //!< Sample Read Position
std::uint64_t m_sampleCount{}; //!< Total number of samples in the file
unsigned int m_sampleRate{}; //!< Number of samples per second
std::vector<SoundChannel> m_channelMap; //!< The map of position in sample frame to sound channel
};
} // namespace sf
////////////////////////////////////////////////////////////
/// \class sf::InputSoundFile
/// \ingroup audio
///
/// This class decodes audio samples from a sound file. It is
/// used internally by higher-level classes such as `sf::SoundBuffer`
/// and `sf::Music`, but can also be useful if you want to process
/// or analyze audio files without playing them, or if you want to
/// implement your own version of `sf::Music` with more specific
/// features.
///
/// Usage example:
/// \code
/// // Open a sound file
/// sf::InputSoundFile file("music.ogg");
///
/// // Print the sound attributes
/// std::cout << "duration: " << file.getDuration().asSeconds() << '\n'
/// << "channels: " << file.getChannelCount() << '\n'
/// << "sample rate: " << file.getSampleRate() << '\n'
/// << "sample count: " << file.getSampleCount() << std::endl;
///
/// // Read and process batches of samples until the end of file is reached
/// std::array<std::int16_t, 1024> samples;
/// std::uint64_t count;
/// do
/// {
/// count = file.read(samples.data(), samples.size());
///
/// // process, analyze, play, convert, or whatever
/// // you want to do with the samples...
/// }
/// while (count > 0);
/// \endcode
///
/// \see `sf::SoundFileReader`, `sf::OutputSoundFile`
///
////////////////////////////////////////////////////////////

View File

@ -1,234 +0,0 @@
////////////////////////////////////////////////////////////
//
// SFML - Simple and Fast Multimedia Library
// Copyright (C) 2007-2025 Laurent Gomila (laurent@sfml-dev.org)
//
// This software is provided 'as-is', without any express or implied warranty.
// In no event will the authors be held liable for any damages arising from the use of this software.
//
// Permission is granted to anyone to use this software for any purpose,
// including commercial applications, and to alter it and redistribute it freely,
// subject to the following restrictions:
//
// 1. The origin of this software must not be misrepresented;
// you must not claim that you wrote the original software.
// If you use this software in a product, an acknowledgment
// in the product documentation would be appreciated but is not required.
//
// 2. Altered source versions must be plainly marked as such,
// and must not be misrepresented as being the original software.
//
// 3. This notice may not be removed or altered from any source distribution.
//
////////////////////////////////////////////////////////////
#pragma once
////////////////////////////////////////////////////////////
// Headers
////////////////////////////////////////////////////////////
#include <SFML/Audio/Export.hpp>
#include <SFML/System/Angle.hpp>
#include <SFML/System/Vector3.hpp>
////////////////////////////////////////////////////////////
/// \brief The audio listener is the point in the scene
/// from where all the sounds are heard
///
////////////////////////////////////////////////////////////
namespace sf::Listener
{
////////////////////////////////////////////////////////////
/// \brief Structure defining the properties of a directional cone
///
/// Sounds will play at gain 1 when they are positioned
/// within the inner angle of the cone. Sounds will play
/// at `outerGain` when they are positioned outside the
/// outer angle of the cone. The gain declines linearly
/// from 1 to `outerGain` as the sound moves from the inner
/// angle to the outer angle.
///
////////////////////////////////////////////////////////////
struct Cone
{
Angle innerAngle; //!< Inner angle
Angle outerAngle; //!< Outer angle
float outerGain{}; //!< Outer gain
};
////////////////////////////////////////////////////////////
/// \brief Change the global volume of all the sounds and musics
///
/// `volume` is a number between 0 and 100; it is combined
/// with the individual volume of each sound / music.
/// The default value for the volume is 100 (maximum).
///
/// \param volume New global volume, in the range [0, 100]
///
/// \see `getGlobalVolume`
///
////////////////////////////////////////////////////////////
SFML_AUDIO_API void setGlobalVolume(float volume);
////////////////////////////////////////////////////////////
/// \brief Get the current value of the global volume
///
/// \return Current global volume, in the range [0, 100]
///
/// \see `setGlobalVolume`
///
////////////////////////////////////////////////////////////
[[nodiscard]] SFML_AUDIO_API float getGlobalVolume();
////////////////////////////////////////////////////////////
/// \brief Set the position of the listener in the scene
///
/// The default listener's position is (0, 0, 0).
///
/// \param position New listener's position
///
/// \see `getPosition`, `setDirection`
///
////////////////////////////////////////////////////////////
SFML_AUDIO_API void setPosition(const Vector3f& position);
////////////////////////////////////////////////////////////
/// \brief Get the current position of the listener in the scene
///
/// \return Listener's position
///
/// \see `setPosition`
///
////////////////////////////////////////////////////////////
[[nodiscard]] SFML_AUDIO_API Vector3f getPosition();
////////////////////////////////////////////////////////////
/// \brief Set the forward vector of the listener in the scene
///
/// The direction (also called "at vector") is the vector
/// pointing forward from the listener's perspective. Together
/// with the up vector, it defines the 3D orientation of the
/// listener in the scene. The direction vector doesn't
/// have to be normalized.
/// The default listener's direction is (0, 0, -1).
///
/// \param direction New listener's direction
///
/// \see `getDirection`, `setUpVector`, `setPosition`
///
////////////////////////////////////////////////////////////
SFML_AUDIO_API void setDirection(const Vector3f& direction);
////////////////////////////////////////////////////////////
/// \brief Get the current forward vector of the listener in the scene
///
/// \return Listener's forward vector (not normalized)
///
/// \see `setDirection`
///
////////////////////////////////////////////////////////////
[[nodiscard]] SFML_AUDIO_API Vector3f getDirection();
////////////////////////////////////////////////////////////
/// \brief Set the velocity of the listener in the scene
///
/// The default listener's velocity is (0, 0, -1).
///
/// \param velocity New listener's velocity
///
/// \see `getVelocity`, `getDirection`, `setUpVector`, `setPosition`
///
////////////////////////////////////////////////////////////
SFML_AUDIO_API void setVelocity(const Vector3f& velocity);
////////////////////////////////////////////////////////////
/// \brief Get the current forward vector of the listener in the scene
///
/// \return Listener's velocity
///
/// \see `setVelocity`
///
////////////////////////////////////////////////////////////
[[nodiscard]] SFML_AUDIO_API Vector3f getVelocity();
////////////////////////////////////////////////////////////
/// \brief Set the cone properties of the listener in the audio scene
///
/// The cone defines how directional attenuation is applied.
/// The default cone of a sound is (2 * PI, 2 * PI, 1).
///
/// \param cone Cone properties of the listener in the scene
///
/// \see `getCone`
///
////////////////////////////////////////////////////////////
SFML_AUDIO_API void setCone(const Listener::Cone& cone);
////////////////////////////////////////////////////////////
/// \brief Get the cone properties of the listener in the audio scene
///
/// \return Cone properties of the listener
///
/// \see `setCone`
///
////////////////////////////////////////////////////////////
[[nodiscard]] SFML_AUDIO_API Listener::Cone getCone();
////////////////////////////////////////////////////////////
/// \brief Set the upward vector of the listener in the scene
///
/// The up vector is the vector that points upward from the
/// listener's perspective. Together with the direction, it
/// defines the 3D orientation of the listener in the scene.
/// The up vector doesn't have to be normalized.
/// The default listener's up vector is (0, 1, 0). It is usually
/// not necessary to change it, especially in 2D scenarios.
///
/// \param upVector New listener's up vector
///
/// \see `getUpVector`, `setDirection`, `setPosition`
///
////////////////////////////////////////////////////////////
SFML_AUDIO_API void setUpVector(const Vector3f& upVector);
////////////////////////////////////////////////////////////
/// \brief Get the current upward vector of the listener in the scene
///
/// \return Listener's upward vector (not normalized)
///
/// \see `setUpVector`
///
////////////////////////////////////////////////////////////
[[nodiscard]] SFML_AUDIO_API Vector3f getUpVector();
} // namespace sf::Listener
////////////////////////////////////////////////////////////
/// \namespace sf::Listener
/// \ingroup audio
///
/// The audio listener defines the global properties of the
/// audio environment, it defines where and how sounds and musics
/// are heard. If `sf::View` is the eyes of the user, then
/// `sf::Listener` are their ears (by the way, they are often linked
/// together -- same position, orientation, etc.).
///
/// `sf::Listener` is a simple interface, which allows to setup the
/// listener in the 3D audio environment (position, direction and
/// up vector), and to adjust the global volume.
///
/// Usage example:
/// \code
/// // Move the listener to the position (1, 0, -5)
/// sf::Listener::setPosition({1, 0, -5});
///
/// // Make it face the right axis (1, 0, 0)
/// sf::Listener::setDirection({1, 0, 0});
///
/// // Reduce the global volume
/// sf::Listener::setGlobalVolume(50);
/// \endcode
///
////////////////////////////////////////////////////////////

View File

@ -1,377 +0,0 @@
////////////////////////////////////////////////////////////
//
// SFML - Simple and Fast Multimedia Library
// Copyright (C) 2007-2025 Laurent Gomila (laurent@sfml-dev.org)
//
// This software is provided 'as-is', without any express or implied warranty.
// In no event will the authors be held liable for any damages arising from the use of this software.
//
// Permission is granted to anyone to use this software for any purpose,
// including commercial applications, and to alter it and redistribute it freely,
// subject to the following restrictions:
//
// 1. The origin of this software must not be misrepresented;
// you must not claim that you wrote the original software.
// If you use this software in a product, an acknowledgment
// in the product documentation would be appreciated but is not required.
//
// 2. Altered source versions must be plainly marked as such,
// and must not be misrepresented as being the original software.
//
// 3. This notice may not be removed or altered from any source distribution.
//
////////////////////////////////////////////////////////////
#pragma once
////////////////////////////////////////////////////////////
// Headers
////////////////////////////////////////////////////////////
#include <SFML/Audio/Export.hpp>
#include <SFML/Audio/SoundStream.hpp>
#include <filesystem>
#include <memory>
#include <optional>
#include <cstddef>
#include <cstdint>
namespace sf
{
class Time;
class InputStream;
class InputSoundFile;
////////////////////////////////////////////////////////////
/// \brief Streamed music played from an audio file
///
////////////////////////////////////////////////////////////
class SFML_AUDIO_API Music : public SoundStream
{
public:
////////////////////////////////////////////////////////////
/// \brief Structure defining a time range using the template type
///
////////////////////////////////////////////////////////////
template <typename T>
struct Span
{
T offset{}; //!< The beginning offset of the time range
T length{}; //!< The length of the time range
};
// Associated `Span` type
using TimeSpan = Span<Time>;
////////////////////////////////////////////////////////////
/// \brief Default constructor
///
/// Construct an empty music that does not contain any data.
///
////////////////////////////////////////////////////////////
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 sf::Exception if loading was unsuccessful
///
/// \see `openFromMemory`, `openFromStream`
///
////////////////////////////////////////////////////////////
explicit 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 sf::Exception 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 `stream` must remain accessible
/// until the `sf::Music` object loads a new music or is destroyed.
///
/// \param stream Source stream to read from
///
/// \throws sf::Exception if loading was unsuccessful
///
/// \see `openFromFile`, `openFromMemory`
///
////////////////////////////////////////////////////////////
explicit Music(InputStream& stream);
////////////////////////////////////////////////////////////
/// \brief Destructor
///
////////////////////////////////////////////////////////////
~Music() override;
////////////////////////////////////////////////////////////
/// \brief Move constructor
///
////////////////////////////////////////////////////////////
Music(Music&&) noexcept;
////////////////////////////////////////////////////////////
/// \brief Move assignment
///
////////////////////////////////////////////////////////////
Music& operator=(Music&&) noexcept;
////////////////////////////////////////////////////////////
/// \brief Open a music from an audio file
///
/// This function doesn't start playing the music (call `play()`
/// to do so).
/// 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 `true` if loading succeeded, `false` if it failed
///
/// \see `openFromMemory`, `openFromStream`
///
////////////////////////////////////////////////////////////
[[nodiscard]] bool openFromFile(const std::filesystem::path& filename);
////////////////////////////////////////////////////////////
/// \brief Open 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 `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 `true` if loading succeeded, `false` if it failed
///
/// \see `openFromFile`, `openFromStream`
///
////////////////////////////////////////////////////////////
[[nodiscard]] bool openFromMemory(const void* data, std::size_t sizeInBytes);
////////////////////////////////////////////////////////////
/// \brief Open a music from an audio file in a custom stream
///
/// This function doesn't start playing the music (call `play()`
/// to do so).
/// 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 `stream` must remain accessible
/// until the `sf::Music` object loads a new music or is destroyed.
///
/// \param stream Source stream to read from
///
/// \return `true` if loading succeeded, `false` if it failed
///
/// \see `openFromFile`, `openFromMemory`
///
////////////////////////////////////////////////////////////
[[nodiscard]] bool openFromStream(InputStream& stream);
////////////////////////////////////////////////////////////
/// \brief Get the total duration of the music
///
/// \return Music duration
///
////////////////////////////////////////////////////////////
[[nodiscard]] Time getDuration() const;
////////////////////////////////////////////////////////////
/// \brief Get the positions of the of the sound's looping sequence
///
/// \return Loop Time position class.
///
/// \warning Since `setLoopPoints()` performs some adjustments on the
/// provided values and rounds them to internal samples, a call to
/// `getLoopPoints()` is not guaranteed to return the same times passed
/// into a previous call to `setLoopPoints()`. However, it is guaranteed
/// to return times that will map to the valid internal samples of
/// this Music if they are later passed to `setLoopPoints()`.
///
/// \see `setLoopPoints`
///
////////////////////////////////////////////////////////////
[[nodiscard]] TimeSpan getLoopPoints() const;
////////////////////////////////////////////////////////////
/// \brief Sets the beginning and duration of the sound's looping sequence using `sf::Time`
///
/// `setLoopPoints()` allows for specifying the beginning offset and the duration of the loop such that,
/// when the music is enabled for looping, it will seamlessly seek to the beginning whenever it
/// encounters the end of the duration. Valid ranges for `timePoints.offset` and `timePoints.length` are
/// [0, Dur) and (0, Dur-offset] respectively, where Dur is the value returned by `getDuration()`.
/// Note that the EOF "loop point" from the end to the beginning of the stream is still honored,
/// in case the caller seeks to a point after the end of the loop range. This function can be
/// safely called at any point after a stream is opened, and will be applied to a playing sound
/// without affecting the current playing offset.
///
/// \warning Setting the loop points while the stream's status is Paused
/// will set its status to Stopped. The playing offset will be unaffected.
///
/// \param timePoints The definition of the loop. Can be any time points within the sound's length
///
/// \see `getLoopPoints`
///
////////////////////////////////////////////////////////////
void setLoopPoints(TimeSpan timePoints);
protected:
////////////////////////////////////////////////////////////
/// \brief Request a new chunk of audio samples from the stream source
///
/// This function fills the chunk from the next samples
/// to read from the audio file.
///
/// \param data Chunk of data to fill
///
/// \return `true` to continue playback, `false` to stop
///
////////////////////////////////////////////////////////////
[[nodiscard]] bool onGetData(Chunk& data) override;
////////////////////////////////////////////////////////////
/// \brief Change the current playing position in the stream source
///
/// \param timeOffset New playing position, from the beginning of the music
///
////////////////////////////////////////////////////////////
void onSeek(Time timeOffset) override;
////////////////////////////////////////////////////////////
/// \brief Change the current playing position in the stream source to the loop offset
///
/// This is called by the underlying `SoundStream` whenever it needs us to reset
/// the seek position for a loop. We then determine whether we are looping on a
/// loop point or the end-of-file, perform the seek, and return the new position.
///
/// \return The seek position after looping (or `std::nullopt` if there's no loop)
///
////////////////////////////////////////////////////////////
std::optional<std::uint64_t> onLoop() override;
private:
////////////////////////////////////////////////////////////
/// \brief Helper to convert an `sf::Time` to a sample position
///
/// \param position Time to convert to samples
///
/// \return The number of samples elapsed at the given time
///
////////////////////////////////////////////////////////////
[[nodiscard]] std::uint64_t timeToSamples(Time position) const;
////////////////////////////////////////////////////////////
/// \brief Helper to convert a sample position to an `sf::Time`
///
/// \param samples Sample count to convert to Time
///
/// \return The Time position of the given sample
///
////////////////////////////////////////////////////////////
[[nodiscard]] Time samplesToTime(std::uint64_t samples) const;
////////////////////////////////////////////////////////////
// Member data
////////////////////////////////////////////////////////////
struct Impl;
std::unique_ptr<Impl> m_impl; //!< Implementation details
};
} // namespace sf
////////////////////////////////////////////////////////////
/// \class sf::Music
/// \ingroup audio
///
/// Musics are sounds that are streamed rather than completely
/// loaded in memory. This is especially useful for compressed
/// musics that usually take hundreds of MB when they are
/// uncompressed: by streaming it instead of loading it entirely,
/// you avoid saturating the memory and have almost no loading delay.
/// This implies that the underlying resource (file, stream or
/// memory buffer) must remain valid for the lifetime of the
/// `sf::Music` object.
///
/// Apart from that, a `sf::Music` has almost the same features as
/// the `sf::SoundBuffer` / `sf::Sound` pair: you can play/pause/stop
/// it, request its parameters (channels, sample rate), change
/// the way it is played (pitch, volume, 3D position, ...), etc.
///
/// As a sound stream, a music is played in its own thread in order
/// not to block the rest of the program. This means that you can
/// leave the music alone after calling `play()`, it will manage itself
/// very well.
///
/// Usage example:
/// \code
/// // Open a music from an audio file
/// sf::Music music("music.ogg");
///
/// // Change some parameters
/// music.setPosition({0, 1, 10}); // change its 3D position
/// music.setPitch(2); // increase the pitch
/// music.setVolume(50); // reduce the volume
/// music.setLooping(true); // make it loop
///
/// // Play it
/// music.play();
/// \endcode
///
/// \see `sf::Sound`, `sf::SoundStream`
///
////////////////////////////////////////////////////////////

View File

@ -1,147 +0,0 @@
////////////////////////////////////////////////////////////
//
// SFML - Simple and Fast Multimedia Library
// Copyright (C) 2007-2025 Laurent Gomila (laurent@sfml-dev.org)
//
// This software is provided 'as-is', without any express or implied warranty.
// In no event will the authors be held liable for any damages arising from the use of this software.
//
// Permission is granted to anyone to use this software for any purpose,
// including commercial applications, and to alter it and redistribute it freely,
// subject to the following restrictions:
//
// 1. The origin of this software must not be misrepresented;
// you must not claim that you wrote the original software.
// If you use this software in a product, an acknowledgment
// in the product documentation would be appreciated but is not required.
//
// 2. Altered source versions must be plainly marked as such,
// and must not be misrepresented as being the original software.
//
// 3. This notice may not be removed or altered from any source distribution.
//
////////////////////////////////////////////////////////////
#pragma once
////////////////////////////////////////////////////////////
// Headers
////////////////////////////////////////////////////////////
#include <SFML/Audio/Export.hpp>
#include <SFML/Audio/SoundChannel.hpp>
#include <SFML/Audio/SoundFileWriter.hpp>
#include <filesystem>
#include <memory>
#include <vector>
#include <cstdint>
namespace sf
{
////////////////////////////////////////////////////////////
/// \brief Provide write access to sound files
///
////////////////////////////////////////////////////////////
class SFML_AUDIO_API OutputSoundFile
{
public:
////////////////////////////////////////////////////////////
/// \brief Default constructor
///
/// Construct an output sound file that is not associated
/// with a file to write.
///
////////////////////////////////////////////////////////////
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 sf::Exception if the file could not be opened successfully
///
////////////////////////////////////////////////////////////
OutputSoundFile(const std::filesystem::path& filename,
unsigned int sampleRate,
unsigned int channelCount,
const std::vector<SoundChannel>& channelMap);
////////////////////////////////////////////////////////////
/// \brief Open the sound file from the disk for writing
///
/// 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 `true` if the file was successfully opened
///
////////////////////////////////////////////////////////////
[[nodiscard]] bool openFromFile(const std::filesystem::path& filename,
unsigned int sampleRate,
unsigned int channelCount,
const std::vector<SoundChannel>& channelMap);
////////////////////////////////////////////////////////////
/// \brief Write audio samples to the file
///
/// \param samples Pointer to the sample array to write
/// \param count Number of samples to write
///
////////////////////////////////////////////////////////////
void write(const std::int16_t* samples, std::uint64_t count);
////////////////////////////////////////////////////////////
/// \brief Close the current file
///
////////////////////////////////////////////////////////////
void close();
private:
////////////////////////////////////////////////////////////
// Member data
////////////////////////////////////////////////////////////
std::unique_ptr<SoundFileWriter> m_writer; //!< Writer that handles I/O on the file's format
};
} // namespace sf
////////////////////////////////////////////////////////////
/// \class sf::OutputSoundFile
/// \ingroup audio
///
/// This class encodes audio samples to a sound file. It is
/// used internally by higher-level classes such as `sf::SoundBuffer`,
/// but can also be useful if you want to create audio files from
/// custom data sources, like generated audio samples.
///
/// Usage example:
/// \code
/// // Create a sound file, ogg/vorbis format, 44100 Hz, stereo
/// sf::OutputSoundFile file("music.ogg", 44100, 2, {sf::SoundChannel::FrontLeft, sf::SoundChannel::FrontRight});
///
/// while (...)
/// {
/// // Read or generate audio samples from your custom source
/// std::vector<std::int16_t> samples = ...;
///
/// // Write them to the file
/// file.write(samples.data(), samples.size());
/// }
/// \endcode
///
/// \see `sf::SoundFileWriter`, `sf::InputSoundFile`
///
////////////////////////////////////////////////////////////

View File

@ -1,110 +0,0 @@
////////////////////////////////////////////////////////////
//
// SFML - Simple and Fast Multimedia Library
// Copyright (C) 2007-2025 Laurent Gomila (laurent@sfml-dev.org)
//
// This software is provided 'as-is', without any express or implied warranty.
// In no event will the authors be held liable for any damages arising from the use of this software.
//
// Permission is granted to anyone to use this software for any purpose,
// including commercial applications, and to alter it and redistribute it freely,
// subject to the following restrictions:
//
// 1. The origin of this software must not be misrepresented;
// you must not claim that you wrote the original software.
// If you use this software in a product, an acknowledgment
// in the product documentation would be appreciated but is not required.
//
// 2. Altered source versions must be plainly marked as such,
// and must not be misrepresented as being the original software.
//
// 3. This notice may not be removed or altered from any source distribution.
//
////////////////////////////////////////////////////////////
#pragma once
////////////////////////////////////////////////////////////
// Headers
////////////////////////////////////////////////////////////
#include <SFML/Audio/Export.hpp>
#include <optional>
#include <string>
#include <vector>
namespace sf::PlaybackDevice
{
////////////////////////////////////////////////////////////
/// \brief Get a list of the names of all available audio playback devices
///
/// This function returns a vector of strings containing
/// the names of all available audio playback devices.
///
/// If the operating system reports multiple devices with
/// the same name, a number will be appended to the name
/// of all subsequent devices to distinguish them from each
/// other. This guarantees that every entry returned by this
/// function will represent a unique device.
///
/// For example, if the operating system reports multiple
/// devices with the name "Sound Card", the entries returned
/// would be:
/// - Sound Card
/// - Sound Card 2
/// - Sound Card 3
/// - ...
///
/// The default device, if one is marked as such, will be
/// placed at the beginning of the vector.
///
/// If no devices are available, this function will return
/// an empty vector.
///
/// \return A vector of strings containing the device names or an empty vector if no devices are available
///
////////////////////////////////////////////////////////////
[[nodiscard]] SFML_AUDIO_API std::vector<std::string> getAvailableDevices();
////////////////////////////////////////////////////////////
/// \brief Get the name of the default audio playback device
///
/// This function returns the name of the default audio
/// playback device. If none is available, an empty string
/// is returned.
///
/// \return The name of the default audio playback device
///
////////////////////////////////////////////////////////////
[[nodiscard]] SFML_AUDIO_API std::optional<std::string> getDefaultDevice();
////////////////////////////////////////////////////////////
/// \brief Set the audio playback device
///
/// This function sets the audio playback device to the device
/// with the given `name`. It can be called on the fly (i.e:
/// while sounds are playing).
///
/// If there are sounds playing when the audio playback
/// device is switched, the sounds will continue playing
/// uninterrupted on the new audio playback device.
///
/// \param name The name of the audio playback device
///
/// \return `true`, if it was able to set the requested device
///
/// \see `getAvailableDevices`, `getDefaultDevice`
///
////////////////////////////////////////////////////////////
[[nodiscard]] SFML_AUDIO_API bool setDevice(const std::string& name);
////////////////////////////////////////////////////////////
/// \brief Get the name of the current audio playback device
///
/// \return The name of the current audio playback device or `std::nullopt` if there is none
///
////////////////////////////////////////////////////////////
[[nodiscard]] SFML_AUDIO_API std::optional<std::string> getDevice();
} // namespace sf::PlaybackDevice

View File

@ -1,284 +0,0 @@
////////////////////////////////////////////////////////////
//
// SFML - Simple and Fast Multimedia Library
// Copyright (C) 2007-2025 Laurent Gomila (laurent@sfml-dev.org)
//
// This software is provided 'as-is', without any express or implied warranty.
// In no event will the authors be held liable for any damages arising from the use of this software.
//
// Permission is granted to anyone to use this software for any purpose,
// including commercial applications, and to alter it and redistribute it freely,
// subject to the following restrictions:
//
// 1. The origin of this software must not be misrepresented;
// you must not claim that you wrote the original software.
// If you use this software in a product, an acknowledgment
// in the product documentation would be appreciated but is not required.
//
// 2. Altered source versions must be plainly marked as such,
// and must not be misrepresented as being the original software.
//
// 3. This notice may not be removed or altered from any source distribution.
//
////////////////////////////////////////////////////////////
#pragma once
////////////////////////////////////////////////////////////
// Headers
////////////////////////////////////////////////////////////
#include <SFML/Audio/Export.hpp>
#include <SFML/Audio/SoundSource.hpp>
#include <memory>
#include <cstdlib>
namespace sf
{
class Time;
class SoundBuffer;
////////////////////////////////////////////////////////////
/// \brief Regular sound that can be played in the audio environment
///
////////////////////////////////////////////////////////////
class SFML_AUDIO_API Sound : public SoundSource
{
public:
////////////////////////////////////////////////////////////
/// \brief Construct the sound with a buffer
///
/// \param buffer Sound buffer containing the audio data to play with the sound
///
////////////////////////////////////////////////////////////
explicit Sound(const SoundBuffer& buffer);
////////////////////////////////////////////////////////////
/// \brief Disallow construction from a temporary sound buffer
///
////////////////////////////////////////////////////////////
Sound(const SoundBuffer&& buffer) = delete;
////////////////////////////////////////////////////////////
/// \brief Copy constructor
///
/// \param copy Instance to copy
///
////////////////////////////////////////////////////////////
Sound(const Sound& copy);
////////////////////////////////////////////////////////////
/// \brief Destructor
///
////////////////////////////////////////////////////////////
~Sound() override;
////////////////////////////////////////////////////////////
/// \brief Start or resume playing the sound
///
/// This function starts the stream if it was stopped, resumes
/// it if it was paused, and restarts it from beginning if it
/// was it already playing.
/// This function uses its own thread so that it doesn't block
/// the rest of the program while the sound is played.
///
/// \see `pause`, `stop`
///
////////////////////////////////////////////////////////////
void play() override;
////////////////////////////////////////////////////////////
/// \brief Pause the sound
///
/// This function pauses the sound if it was playing,
/// otherwise (sound already paused or stopped) it has no effect.
///
/// \see `play`, `stop`
///
////////////////////////////////////////////////////////////
void pause() override;
////////////////////////////////////////////////////////////
/// \brief stop playing the sound
///
/// This function stops the sound if it was playing or paused,
/// and does nothing if it was already stopped.
/// It also resets the playing position (unlike `pause()`).
///
/// \see `play`, `pause`
///
////////////////////////////////////////////////////////////
void stop() override;
////////////////////////////////////////////////////////////
/// \brief Set the source buffer containing the audio data to play
///
/// It is important to note that the sound buffer is not copied,
/// thus the `sf::SoundBuffer` instance must remain alive as long
/// as it is attached to the sound.
///
/// \param buffer Sound buffer to attach to the sound
///
/// \see `getBuffer`
///
////////////////////////////////////////////////////////////
void setBuffer(const SoundBuffer& buffer);
////////////////////////////////////////////////////////////
/// \brief Disallow setting from a temporary sound buffer
///
////////////////////////////////////////////////////////////
void setBuffer(const SoundBuffer&& buffer) = delete;
////////////////////////////////////////////////////////////
/// \brief Set whether or not the sound should loop after reaching the end
///
/// If set, the sound will restart from beginning after
/// reaching the end and so on, until it is stopped or
/// `setLooping(false)` is called.
/// The default looping state for sound is `false`.
///
/// \param loop `true` to play in loop, `false` to play once
///
/// \see `isLooping`
///
////////////////////////////////////////////////////////////
void setLooping(bool loop);
////////////////////////////////////////////////////////////
/// \brief Change the current playing position of the sound
///
/// The playing position can be changed when the sound is
/// either paused or playing. Changing the playing position
/// when the sound is stopped has no effect, since playing
/// the sound will reset its position.
///
/// \param timeOffset New playing position, from the beginning of the sound
///
/// \see `getPlayingOffset`
///
////////////////////////////////////////////////////////////
void setPlayingOffset(Time timeOffset);
////////////////////////////////////////////////////////////
/// \brief Set the effect processor to be applied to the sound
///
/// The effect processor is a callable that will be called
/// with sound data to be processed.
///
/// \param effectProcessor The effect processor to attach to this sound, attach an empty processor to disable processing
///
////////////////////////////////////////////////////////////
void setEffectProcessor(EffectProcessor effectProcessor) override;
////////////////////////////////////////////////////////////
/// \brief Get the audio buffer attached to the sound
///
/// \return Sound buffer attached to the sound
///
////////////////////////////////////////////////////////////
[[nodiscard]] const SoundBuffer& getBuffer() const;
////////////////////////////////////////////////////////////
/// \brief Tell whether or not the sound is in loop mode
///
/// \return `true` if the sound is looping, `false` otherwise
///
/// \see `setLooping`
///
////////////////////////////////////////////////////////////
[[nodiscard]] bool isLooping() const;
////////////////////////////////////////////////////////////
/// \brief Get the current playing position of the sound
///
/// \return Current playing position, from the beginning of the sound
///
/// \see `setPlayingOffset`
///
////////////////////////////////////////////////////////////
[[nodiscard]] Time getPlayingOffset() const;
////////////////////////////////////////////////////////////
/// \brief Get the current status of the sound (stopped, paused, playing)
///
/// \return Current status of the sound
///
////////////////////////////////////////////////////////////
[[nodiscard]] Status getStatus() const override;
////////////////////////////////////////////////////////////
/// \brief Overload of assignment operator
///
/// \param right Instance to assign
///
/// \return Reference to self
///
////////////////////////////////////////////////////////////
Sound& operator=(const Sound& right);
private:
friend class SoundBuffer;
////////////////////////////////////////////////////////////
/// \brief Detach sound from its internal buffer
///
/// This allows the sound buffer to temporarily detach the
/// sounds that use it when the sound buffer gets updated.
///
////////////////////////////////////////////////////////////
void detachBuffer();
////////////////////////////////////////////////////////////
/// \brief Get the sound object
///
/// \return The sound object
///
////////////////////////////////////////////////////////////
[[nodiscard]] void* getSound() const override;
////////////////////////////////////////////////////////////
// Member data
////////////////////////////////////////////////////////////
struct Impl;
const std::unique_ptr<Impl> m_impl; //!< Implementation details
};
} // namespace sf
////////////////////////////////////////////////////////////
/// \class sf::Sound
/// \ingroup audio
///
/// `sf::Sound` is the class to use to play sounds.
/// It provides:
/// \li Control (play, pause, stop)
/// \li Ability to modify output parameters in real-time (pitch, volume, ...)
/// \li 3D spatial features (position, attenuation, ...).
///
/// `sf::Sound` is perfect for playing short sounds that can
/// fit in memory and require no latency, like foot steps or
/// gun shots. For longer sounds, like background musics
/// or long speeches, rather see `sf::Music` (which is based
/// on streaming).
///
/// In order to work, a sound must be given a buffer of audio
/// data to play. Audio data (samples) is stored in `sf::SoundBuffer,`
/// and attached to a sound when it is created or with the `setBuffer()` function.
/// The buffer object attached to a sound must remain alive
/// as long as the sound uses it. Note that multiple sounds
/// can use the same sound buffer at the same time.
///
/// Usage example:
/// \code
/// const sf::SoundBuffer buffer("sound.wav");
/// sf::Sound sound(buffer);
/// sound.play();
/// \endcode
///
/// \see `sf::SoundBuffer`, `sf::Music`
///
////////////////////////////////////////////////////////////

View File

@ -1,451 +0,0 @@
////////////////////////////////////////////////////////////
//
// SFML - Simple and Fast Multimedia Library
// Copyright (C) 2007-2025 Laurent Gomila (laurent@sfml-dev.org)
//
// This software is provided 'as-is', without any express or implied warranty.
// In no event will the authors be held liable for any damages arising from the use of this software.
//
// Permission is granted to anyone to use this software for any purpose,
// including commercial applications, and to alter it and redistribute it freely,
// subject to the following restrictions:
//
// 1. The origin of this software must not be misrepresented;
// you must not claim that you wrote the original software.
// If you use this software in a product, an acknowledgment
// in the product documentation would be appreciated but is not required.
//
// 2. Altered source versions must be plainly marked as such,
// and must not be misrepresented as being the original software.
//
// 3. This notice may not be removed or altered from any source distribution.
//
////////////////////////////////////////////////////////////
#pragma once
////////////////////////////////////////////////////////////
// Headers
////////////////////////////////////////////////////////////
#include <SFML/Audio/Export.hpp>
#include <SFML/Audio/SoundChannel.hpp>
#include <SFML/System/Time.hpp>
#include <filesystem>
#include <unordered_set>
#include <vector>
#include <cstddef>
#include <cstdint>
namespace sf
{
class Sound;
class InputSoundFile;
class InputStream;
////////////////////////////////////////////////////////////
/// \brief Storage for audio samples defining a sound
///
////////////////////////////////////////////////////////////
class SFML_AUDIO_API SoundBuffer
{
public:
////////////////////////////////////////////////////////////
/// \brief Default constructor
///
/// Construct an empty sound buffer that does not contain
/// any samples.
///
////////////////////////////////////////////////////////////
SoundBuffer() = default;
////////////////////////////////////////////////////////////
/// \brief Copy constructor
///
/// \param copy Instance to copy
///
////////////////////////////////////////////////////////////
SoundBuffer(const SoundBuffer& copy);
////////////////////////////////////////////////////////////
/// \brief Construct the sound buffer from a file
///
/// See the documentation of `sf::InputSoundFile` for the list
/// of supported formats.
///
/// \param filename Path of the sound file to load
///
/// \throws sf::Exception if loading was unsuccessful
///
/// \see `loadFromMemory`, `loadFromStream`, `loadFromSamples`, `saveToFile`
///
////////////////////////////////////////////////////////////
explicit 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 sf::Exception 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 sf::Exception if loading was unsuccessful
///
/// \see `loadFromFile`, `loadFromMemory`, `loadFromSamples`
///
////////////////////////////////////////////////////////////
explicit 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 sf::Exception if loading was unsuccessful
///
/// \see `loadFromFile`, `loadFromMemory`, `saveToFile`
///
////////////////////////////////////////////////////////////
SoundBuffer(const std::int16_t* samples,
std::uint64_t sampleCount,
unsigned int channelCount,
unsigned int sampleRate,
const std::vector<SoundChannel>& channelMap);
////////////////////////////////////////////////////////////
/// \brief Destructor
///
////////////////////////////////////////////////////////////
~SoundBuffer();
////////////////////////////////////////////////////////////
/// \brief Load the sound buffer from a file
///
/// See the documentation of `sf::InputSoundFile` for the list
/// of supported formats.
///
/// \param filename Path of the sound file to load
///
/// \return `true` if loading succeeded, `false` if it failed
///
/// \see `loadFromMemory`, `loadFromStream`, `loadFromSamples`, `saveToFile`
///
////////////////////////////////////////////////////////////
[[nodiscard]] bool loadFromFile(const std::filesystem::path& filename);
////////////////////////////////////////////////////////////
/// \brief Load 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 `true` if loading succeeded, `false` if it failed
///
/// \see `loadFromFile`, `loadFromStream`, `loadFromSamples`
///
////////////////////////////////////////////////////////////
[[nodiscard]] bool loadFromMemory(const void* data, std::size_t sizeInBytes);
////////////////////////////////////////////////////////////
/// \brief Load the sound buffer from a custom stream
///
/// See the documentation of `sf::InputSoundFile` for the list
/// of supported formats.
///
/// \param stream Source stream to read from
///
/// \return `true` if loading succeeded, `false` if it failed
///
/// \see `loadFromFile`, `loadFromMemory`, `loadFromSamples`
///
////////////////////////////////////////////////////////////
[[nodiscard]] bool loadFromStream(InputStream& stream);
////////////////////////////////////////////////////////////
/// \brief Load 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
///
/// \return `true` if loading succeeded, `false` if it failed
///
/// \see `loadFromFile`, `loadFromMemory`, `saveToFile`
///
////////////////////////////////////////////////////////////
[[nodiscard]] bool loadFromSamples(const std::int16_t* samples,
std::uint64_t sampleCount,
unsigned int channelCount,
unsigned int sampleRate,
const std::vector<SoundChannel>& channelMap);
////////////////////////////////////////////////////////////
/// \brief Save the sound buffer to an audio file
///
/// See the documentation of `sf::OutputSoundFile` for the list
/// of supported formats.
///
/// \param filename Path of the sound file to write
///
/// \return `true` if saving succeeded, `false` if it failed
///
////////////////////////////////////////////////////////////
[[nodiscard]] bool saveToFile(const std::filesystem::path& filename) const;
////////////////////////////////////////////////////////////
/// \brief Get the array of audio samples stored in the buffer
///
/// The format of the returned samples is 16 bit signed integer.
/// The total number of samples in this array is given by the
/// `getSampleCount()` function.
///
/// \return Read-only pointer to the array of sound samples
///
/// \see `getSampleCount`
///
////////////////////////////////////////////////////////////
[[nodiscard]] const std::int16_t* getSamples() const;
////////////////////////////////////////////////////////////
/// \brief Get the number of samples stored in the buffer
///
/// The array of samples can be accessed with the `getSamples()`
/// function.
///
/// \return Number of samples
///
/// \see `getSamples`
///
////////////////////////////////////////////////////////////
[[nodiscard]] std::uint64_t getSampleCount() const;
////////////////////////////////////////////////////////////
/// \brief Get the sample rate of the sound
///
/// The sample rate is the number of samples played per second.
/// The higher, the better the quality (for example, 44100
/// samples/s is CD quality).
///
/// \return Sample rate (number of samples per second)
///
/// \see `getChannelCount`, `getChannelMap`, `getDuration`
///
////////////////////////////////////////////////////////////
[[nodiscard]] unsigned int getSampleRate() const;
////////////////////////////////////////////////////////////
/// \brief Get the number of channels used by the sound
///
/// If the sound is mono then the number of channels will
/// be 1, 2 for stereo, etc.
///
/// \return Number of channels
///
/// \see `getSampleRate`, `getChannelMap`, `getDuration`
///
////////////////////////////////////////////////////////////
[[nodiscard]] unsigned int getChannelCount() const;
////////////////////////////////////////////////////////////
/// \brief Get the map of position in sample frame to sound channel
///
/// This is used to map a sample in the sample stream to a
/// position during spatialization.
///
/// \return Map of position in sample frame to sound channel
///
/// \see `getSampleRate`, `getChannelCount`, `getDuration`
///
////////////////////////////////////////////////////////////
[[nodiscard]] std::vector<SoundChannel> getChannelMap() const;
////////////////////////////////////////////////////////////
/// \brief Get the total duration of the sound
///
/// \return Sound duration
///
/// \see `getSampleRate`, `getChannelCount`, `getChannelMap`
///
////////////////////////////////////////////////////////////
[[nodiscard]] Time getDuration() const;
////////////////////////////////////////////////////////////
/// \brief Overload of assignment operator
///
/// \param right Instance to assign
///
/// \return Reference to self
///
////////////////////////////////////////////////////////////
SoundBuffer& operator=(const SoundBuffer& right);
private:
friend class Sound;
////////////////////////////////////////////////////////////
/// \brief Initialize the internal state after loading a new sound
///
/// \param file Sound file providing access to the new loaded sound
///
/// \return `true` on successful initialization, `false` on failure
///
////////////////////////////////////////////////////////////
[[nodiscard]] bool initialize(InputSoundFile& file);
////////////////////////////////////////////////////////////
/// \brief Update the internal buffer with the cached audio samples
///
/// \param channelCount Number of channels
/// \param sampleRate Sample rate (number of samples per second)
/// \param channelMap Map of position in sample frame to sound channel
///
/// \return `true` on success, `false` if any error happened
///
////////////////////////////////////////////////////////////
[[nodiscard]] bool update(unsigned int channelCount, unsigned int sampleRate, const std::vector<SoundChannel>& channelMap);
////////////////////////////////////////////////////////////
/// \brief Add a sound to the list of sounds that use this buffer
///
/// \param sound Sound instance to attach
///
////////////////////////////////////////////////////////////
void attachSound(Sound* sound) const;
////////////////////////////////////////////////////////////
/// \brief Remove a sound from the list of sounds that use this buffer
///
/// \param sound Sound instance to detach
///
////////////////////////////////////////////////////////////
void detachSound(Sound* sound) const;
////////////////////////////////////////////////////////////
// Types
////////////////////////////////////////////////////////////
using SoundList = std::unordered_set<Sound*>; //!< Set of unique sound instances
////////////////////////////////////////////////////////////
// Member data
////////////////////////////////////////////////////////////
std::vector<std::int16_t> m_samples; //!< Samples buffer
unsigned int m_sampleRate{44100}; //!< Number of samples per second
std::vector<SoundChannel> m_channelMap{SoundChannel::Mono}; //!< The map of position in sample frame to sound channel
Time m_duration; //!< Sound duration
mutable SoundList m_sounds; //!< List of sounds that are using this buffer
};
} // namespace sf
////////////////////////////////////////////////////////////
/// \class sf::SoundBuffer
/// \ingroup audio
///
/// A sound buffer holds the data of a sound, which is
/// an array of audio samples. A sample is a 16 bit signed integer
/// that defines the amplitude of the sound at a given time.
/// The sound is then reconstituted by playing these samples at
/// a high rate (for example, 44100 samples per second is the
/// standard rate used for playing CDs). In short, audio samples
/// are like texture pixels, and a `sf::SoundBuffer` is similar to
/// a `sf::Texture`.
///
/// 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.
///
/// Sound buffers alone are not very useful: they hold the audio data
/// but cannot be played. To do so, you need to use the `sf::Sound` class,
/// which provides functions to play/pause/stop the sound as well as
/// changing the way it is outputted (volume, pitch, 3D position, ...).
/// This separation allows more flexibility and better performances:
/// indeed a `sf::SoundBuffer` is a heavy resource, and any operation on it
/// is slow (often too slow for real-time applications). On the other
/// side, a `sf::Sound` is a lightweight object, which can use the audio data
/// of a sound buffer and change the way it is played without actually
/// modifying that data. Note that it is also possible to bind
/// several `sf::Sound` instances to the same `sf::SoundBuffer`.
///
/// It is important to note that the `sf::Sound` instance doesn't
/// copy the buffer that it uses, it only keeps a reference to it.
/// Thus, a `sf::SoundBuffer` must not be destructed while it is
/// used by a `sf::Sound` (i.e. never write a function that
/// uses a local `sf::SoundBuffer` instance for loading a sound).
///
/// When loading sound samples from an array, a channel map needs to be
/// provided, which specifies the mapping of the position in the sample frame
/// to the sound channel. For example when you have six samples in a frame and
/// a 5.1 sound system, the channel map defines how each of those samples map
/// to which speaker channel.
///
/// Usage example:
/// \code
/// // Load a new sound buffer from a file
/// const sf::SoundBuffer buffer("sound.wav");
///
/// // Create a sound source bound to the buffer
/// sf::Sound sound1(buffer);
///
/// // Play the sound
/// sound1.play();
///
/// // Create another sound source bound to the same buffer
/// sf::Sound sound2(buffer);
///
/// // Play it with a higher pitch -- the first sound remains unchanged
/// sound2.setPitch(2);
/// sound2.play();
///
/// // Load samples with a channel map
/// auto samples = std::vector<std::int16_t>();
/// // ...
/// auto channelMap = std::vector<sf::SoundChannel>{
/// sf::SoundChannel::FrontLeft,
/// sf::SoundChannel::FrontCenter,
/// sf::SoundChannel::FrontRight,
/// sf::SoundChannel::BackRight,
/// sf::SoundChannel::BackLeft,
/// sf::SoundChannel::LowFrequencyEffects
/// };
/// auto soundBuffer = sf::SoundBuffer(samples.data(), samples.size(), channelMap.size(), 44100, channelMap);
/// auto sound = sf::Sound(soundBuffer);
/// \endcode
///
/// \see `sf::Sound`, `sf::SoundBufferRecorder`
///
////////////////////////////////////////////////////////////

View File

@ -1,149 +0,0 @@
////////////////////////////////////////////////////////////
//
// SFML - Simple and Fast Multimedia Library
// Copyright (C) 2007-2025 Laurent Gomila (laurent@sfml-dev.org)
//
// This software is provided 'as-is', without any express or implied warranty.
// In no event will the authors be held liable for any damages arising from the use of this software.
//
// Permission is granted to anyone to use this software for any purpose,
// including commercial applications, and to alter it and redistribute it freely,
// subject to the following restrictions:
//
// 1. The origin of this software must not be misrepresented;
// you must not claim that you wrote the original software.
// If you use this software in a product, an acknowledgment
// in the product documentation would be appreciated but is not required.
//
// 2. Altered source versions must be plainly marked as such,
// and must not be misrepresented as being the original software.
//
// 3. This notice may not be removed or altered from any source distribution.
//
////////////////////////////////////////////////////////////
#pragma once
////////////////////////////////////////////////////////////
// Headers
////////////////////////////////////////////////////////////
#include <SFML/Audio/Export.hpp>
#include <SFML/Audio/SoundBuffer.hpp>
#include <SFML/Audio/SoundRecorder.hpp>
#include <vector>
#include <cstddef>
#include <cstdint>
namespace sf
{
////////////////////////////////////////////////////////////
/// \brief Specialized SoundRecorder which stores the captured
/// audio data into a sound buffer
///
////////////////////////////////////////////////////////////
class SFML_AUDIO_API SoundBufferRecorder : public SoundRecorder
{
public:
////////////////////////////////////////////////////////////
/// \brief destructor
///
////////////////////////////////////////////////////////////
~SoundBufferRecorder() override;
////////////////////////////////////////////////////////////
/// \brief Get the sound buffer containing the captured audio data
///
/// The sound buffer is valid only after the capture has ended.
/// This function provides a read-only access to the internal
/// sound buffer, but it can be copied if you need to
/// make any modification to it.
///
/// \return Read-only access to the sound buffer
///
////////////////////////////////////////////////////////////
[[nodiscard]] const SoundBuffer& getBuffer() const;
protected:
////////////////////////////////////////////////////////////
/// \brief Start capturing audio data
///
/// \return `true` to start the capture, or `false` to abort it
///
////////////////////////////////////////////////////////////
[[nodiscard]] bool onStart() override;
////////////////////////////////////////////////////////////
/// \brief Process a new chunk of recorded samples
///
/// \param samples Pointer to the new chunk of recorded samples
/// \param sampleCount Number of samples pointed by \a samples
///
/// \return `true` to continue the capture, or `false` to stop it
///
////////////////////////////////////////////////////////////
[[nodiscard]] bool onProcessSamples(const std::int16_t* samples, std::size_t sampleCount) override;
////////////////////////////////////////////////////////////
/// \brief Stop capturing audio data
///
////////////////////////////////////////////////////////////
void onStop() override;
private:
////////////////////////////////////////////////////////////
// Member data
////////////////////////////////////////////////////////////
std::vector<std::int16_t> m_samples; //!< Temporary sample buffer to hold the recorded data
SoundBuffer m_buffer; //!< Sound buffer that will contain the recorded data
};
} // namespace sf
////////////////////////////////////////////////////////////
/// \class sf::SoundBufferRecorder
/// \ingroup audio
///
/// `sf::SoundBufferRecorder` allows to access a recorded sound
/// through a `sf::SoundBuffer`, so that it can be played, saved
/// to a file, etc.
///
/// It has the same simple interface as its base class (`start()`, `stop()`)
/// and adds a function to retrieve the recorded sound buffer
/// (`getBuffer()`).
///
/// As usual, don't forget to call the `isAvailable()` function
/// before using this class (see `sf::SoundRecorder` for more details
/// about this).
///
/// Usage example:
/// \code
/// if (sf::SoundBufferRecorder::isAvailable())
/// {
/// // Record some audio data
/// sf::SoundBufferRecorder recorder;
/// if (!recorder.start())
/// {
/// // Handle error...
/// }
/// ...
/// recorder.stop();
///
/// // Get the buffer containing the captured audio data
/// const sf::SoundBuffer& buffer = recorder.getBuffer();
///
/// // Save it to a file (for example...)
/// if (!buffer.saveToFile("my_record.ogg"))
/// {
/// // Handle error...
/// }
/// }
/// \endcode
///
/// \see `sf::SoundRecorder`
///
////////////////////////////////////////////////////////////

View File

@ -1,65 +0,0 @@
////////////////////////////////////////////////////////////
//
// SFML - Simple and Fast Multimedia Library
// Copyright (C) 2007-2025 Laurent Gomila (laurent@sfml-dev.org)
//
// This software is provided 'as-is', without any express or implied warranty.
// In no event will the authors be held liable for any damages arising from the use of this software.
//
// Permission is granted to anyone to use this software for any purpose,
// including commercial applications, and to alter it and redistribute it freely,
// subject to the following restrictions:
//
// 1. The origin of this software must not be misrepresented;
// you must not claim that you wrote the original software.
// If you use this software in a product, an acknowledgment
// in the product documentation would be appreciated but is not required.
//
// 2. Altered source versions must be plainly marked as such,
// and must not be misrepresented as being the original software.
//
// 3. This notice may not be removed or altered from any source distribution.
//
////////////////////////////////////////////////////////////
#pragma once
namespace sf
{
////////////////////////////////////////////////////////////
/// \ingroup audio
/// \brief Types of sound channels that can be read/written from sound buffers/files
///
/// In multi-channel audio, each sound channel can be
/// assigned a position. The position of the channel is
/// used to determine where to place a sound when it
/// is spatialized. Assigning an incorrect sound channel
/// will result in multi-channel audio being positioned
/// incorrectly when using spatialization.
///
////////////////////////////////////////////////////////////
enum class SoundChannel
{
Unspecified,
Mono,
FrontLeft,
FrontRight,
FrontCenter,
FrontLeftOfCenter,
FrontRightOfCenter,
LowFrequencyEffects,
BackLeft,
BackRight,
BackCenter,
SideLeft,
SideRight,
TopCenter,
TopFrontLeft,
TopFrontRight,
TopFrontCenter,
TopBackLeft,
TopBackRight,
TopBackCenter
};
} // namespace sf

View File

@ -1,200 +0,0 @@
////////////////////////////////////////////////////////////
//
// SFML - Simple and Fast Multimedia Library
// Copyright (C) 2007-2025 Laurent Gomila (laurent@sfml-dev.org)
//
// This software is provided 'as-is', without any express or implied warranty.
// In no event will the authors be held liable for any damages arising from the use of this software.
//
// Permission is granted to anyone to use this software for any purpose,
// including commercial applications, and to alter it and redistribute it freely,
// subject to the following restrictions:
//
// 1. The origin of this software must not be misrepresented;
// you must not claim that you wrote the original software.
// If you use this software in a product, an acknowledgment
// in the product documentation would be appreciated but is not required.
//
// 2. Altered source versions must be plainly marked as such,
// and must not be misrepresented as being the original software.
//
// 3. This notice may not be removed or altered from any source distribution.
//
////////////////////////////////////////////////////////////
#pragma once
////////////////////////////////////////////////////////////
// Headers
////////////////////////////////////////////////////////////
#include <SFML/Audio/Export.hpp>
#include <filesystem>
#include <memory>
#include <unordered_map>
#include <cstddef>
namespace sf
{
class InputStream;
class SoundFileReader;
class SoundFileWriter;
////////////////////////////////////////////////////////////
/// \brief Manages and instantiates sound file readers and writers
///
////////////////////////////////////////////////////////////
class SFML_AUDIO_API SoundFileFactory
{
public:
////////////////////////////////////////////////////////////
/// \brief Register a new reader
///
/// \see `unregisterReader`
///
////////////////////////////////////////////////////////////
template <typename T>
static void registerReader();
////////////////////////////////////////////////////////////
/// \brief Unregister a reader
///
/// \see `registerReader`
///
////////////////////////////////////////////////////////////
template <typename T>
static void unregisterReader();
////////////////////////////////////////////////////////////
/// \brief Check if a reader is registered
///
////////////////////////////////////////////////////////////
template <typename T>
[[nodiscard]] static bool isReaderRegistered();
////////////////////////////////////////////////////////////
/// \brief Register a new writer
///
/// \see `unregisterWriter`
///
////////////////////////////////////////////////////////////
template <typename T>
static void registerWriter();
////////////////////////////////////////////////////////////
/// \brief Unregister a writer
///
/// \see `registerWriter`
///
////////////////////////////////////////////////////////////
template <typename T>
static void unregisterWriter();
////////////////////////////////////////////////////////////
/// \brief Check if a writer is registered
///
////////////////////////////////////////////////////////////
template <typename T>
[[nodiscard]] static bool isWriterRegistered();
////////////////////////////////////////////////////////////
/// \brief Instantiate the right reader for the given file on disk
///
/// \param filename Path of the sound file
///
/// \return A new sound file reader that can read the given file, or null if no reader can handle it
///
/// \see `createReaderFromMemory`, `createReaderFromStream`
///
////////////////////////////////////////////////////////////
[[nodiscard]] static std::unique_ptr<SoundFileReader> createReaderFromFilename(const std::filesystem::path& filename);
////////////////////////////////////////////////////////////
/// \brief Instantiate the right codec for the given file in memory
///
/// \param data Pointer to the file data in memory
/// \param sizeInBytes Total size of the file data, in bytes
///
/// \return A new sound file codec that can read the given file, or null if no codec can handle it
///
/// \see `createReaderFromFilename`, `createReaderFromStream`
///
////////////////////////////////////////////////////////////
[[nodiscard]] static std::unique_ptr<SoundFileReader> createReaderFromMemory(const void* data, std::size_t sizeInBytes);
////////////////////////////////////////////////////////////
/// \brief Instantiate the right codec for the given file in stream
///
/// \param stream Source stream to read from
///
/// \return A new sound file codec that can read the given file, or null if no codec can handle it
///
/// \see `createReaderFromFilename`, `createReaderFromMemory`
///
////////////////////////////////////////////////////////////
[[nodiscard]] static std::unique_ptr<SoundFileReader> createReaderFromStream(InputStream& stream);
////////////////////////////////////////////////////////////
/// \brief Instantiate the right writer for the given file on disk
///
/// \param filename Path of the sound file
///
/// \return A new sound file writer that can write given file, or null if no writer can handle it
///
////////////////////////////////////////////////////////////
[[nodiscard]] static std::unique_ptr<SoundFileWriter> createWriterFromFilename(const std::filesystem::path& filename);
private:
////////////////////////////////////////////////////////////
// Types
////////////////////////////////////////////////////////////
template <typename T>
using CreateFnPtr = std::unique_ptr<T> (*)();
using ReaderCheckFnPtr = bool (*)(InputStream&);
using WriterCheckFnPtr = bool (*)(const std::filesystem::path&);
using ReaderFactoryMap = std::unordered_map<CreateFnPtr<SoundFileReader>, ReaderCheckFnPtr>;
using WriterFactoryMap = std::unordered_map<CreateFnPtr<SoundFileWriter>, WriterCheckFnPtr>;
////////////////////////////////////////////////////////////
// Static member functions
////////////////////////////////////////////////////////////
[[nodiscard]] static ReaderFactoryMap& getReaderFactoryMap();
[[nodiscard]] static WriterFactoryMap& getWriterFactoryMap();
};
} // namespace sf
#include <SFML/Audio/SoundFileFactory.inl>
////////////////////////////////////////////////////////////
/// \class sf::SoundFileFactory
/// \ingroup audio
///
/// This class is where all the sound file readers and writers are
/// registered. You should normally only need to use its registration
/// and unregistration functions; readers/writers creation and manipulation
/// are wrapped into the higher-level classes `sf::InputSoundFile` and
/// `sf::OutputSoundFile`.
///
/// To register a new reader (writer) use the `sf::SoundFileFactory::registerReader`
/// (`registerWriter`) static function. You don't have to call the `unregisterReader`
/// (`unregisterWriter`) function, unless you want to unregister a format before your
/// application ends (typically, when a plugin is unloaded).
///
/// Usage example:
/// \code
/// sf::SoundFileFactory::registerReader<MySoundFileReader>();
/// assert(sf::SoundFileFactory::isReaderRegistered<MySoundFileReader>());
///
/// sf::SoundFileFactory::registerWriter<MySoundFileWriter>();
/// assert(sf::SoundFileFactory::isWriterRegistered<MySoundFileWriter>());
/// \endcode
///
/// \see `sf::InputSoundFile`, `sf::OutputSoundFile`, `sf::SoundFileReader`, `sf::SoundFileWriter`
///
////////////////////////////////////////////////////////////

View File

@ -1,96 +0,0 @@
////////////////////////////////////////////////////////////
//
// SFML - Simple and Fast Multimedia Library
// Copyright (C) 2007-2025 Laurent Gomila (laurent@sfml-dev.org)
//
// This software is provided 'as-is', without any express or implied warranty.
// In no event will the authors be held liable for any damages arising from the use of this software.
//
// Permission is granted to anyone to use this software for any purpose,
// including commercial applications, and to alter it and redistribute it freely,
// subject to the following restrictions:
//
// 1. The origin of this software must not be misrepresented;
// you must not claim that you wrote the original software.
// If you use this software in a product, an acknowledgment
// in the product documentation would be appreciated but is not required.
//
// 2. Altered source versions must be plainly marked as such,
// and must not be misrepresented as being the original software.
//
// 3. This notice may not be removed or altered from any source distribution.
//
////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////
// Headers
////////////////////////////////////////////////////////////
#include <SFML/Audio/SoundFileFactory.hpp> // NOLINT(misc-header-include-cycle)
#include <memory>
namespace sf
{
namespace priv
{
template <typename T>
std::unique_ptr<SoundFileReader> createReader()
{
return std::make_unique<T>();
}
template <typename T>
std::unique_ptr<SoundFileWriter> createWriter()
{
return std::make_unique<T>();
}
} // namespace priv
////////////////////////////////////////////////////////////
template <typename T>
void SoundFileFactory::registerReader()
{
getReaderFactoryMap()[&priv::createReader<T>] = &T::check;
}
////////////////////////////////////////////////////////////
template <typename T>
void SoundFileFactory::unregisterReader()
{
getReaderFactoryMap().erase(&priv::createReader<T>);
}
////////////////////////////////////////////////////////////
template <typename T>
bool SoundFileFactory::isReaderRegistered()
{
return getReaderFactoryMap().count(&priv::createReader<T>) == 1;
}
////////////////////////////////////////////////////////////
template <typename T>
void SoundFileFactory::registerWriter()
{
getWriterFactoryMap()[&priv::createWriter<T>] = &T::check;
}
////////////////////////////////////////////////////////////
template <typename T>
void SoundFileFactory::unregisterWriter()
{
getWriterFactoryMap().erase(&priv::createWriter<T>);
}
////////////////////////////////////////////////////////////
template <typename T>
bool SoundFileFactory::isWriterRegistered()
{
return getWriterFactoryMap().count(&priv::createWriter<T>) == 1;
}
} // namespace sf

View File

@ -1,167 +0,0 @@
////////////////////////////////////////////////////////////
//
// SFML - Simple and Fast Multimedia Library
// Copyright (C) 2007-2025 Laurent Gomila (laurent@sfml-dev.org)
//
// This software is provided 'as-is', without any express or implied warranty.
// In no event will the authors be held liable for any damages arising from the use of this software.
//
// Permission is granted to anyone to use this software for any purpose,
// including commercial applications, and to alter it and redistribute it freely,
// subject to the following restrictions:
//
// 1. The origin of this software must not be misrepresented;
// you must not claim that you wrote the original software.
// If you use this software in a product, an acknowledgment
// in the product documentation would be appreciated but is not required.
//
// 2. Altered source versions must be plainly marked as such,
// and must not be misrepresented as being the original software.
//
// 3. This notice may not be removed or altered from any source distribution.
//
////////////////////////////////////////////////////////////
#pragma once
////////////////////////////////////////////////////////////
// Headers
////////////////////////////////////////////////////////////
#include <SFML/Audio/Export.hpp>
#include <SFML/Audio/SoundChannel.hpp>
#include <optional>
#include <vector>
#include <cstdint>
namespace sf
{
class InputStream;
////////////////////////////////////////////////////////////
/// \brief Abstract base class for sound file decoding
///
////////////////////////////////////////////////////////////
class SFML_AUDIO_API SoundFileReader
{
public:
////////////////////////////////////////////////////////////
/// \brief Structure holding the audio properties of a sound file
///
////////////////////////////////////////////////////////////
struct Info
{
std::uint64_t sampleCount{}; //!< Total number of samples in the file
unsigned int channelCount{}; //!< Number of channels of the sound
unsigned int sampleRate{}; //!< Samples rate of the sound, in samples per second
std::vector<SoundChannel> channelMap; //!< Map of position in sample frame to sound channel
};
////////////////////////////////////////////////////////////
/// \brief Virtual destructor
///
////////////////////////////////////////////////////////////
virtual ~SoundFileReader() = default;
////////////////////////////////////////////////////////////
/// \brief Open a sound file for reading
///
/// The provided stream reference is valid as long as the
/// `SoundFileReader` is alive, so it is safe to use/store it
/// during the whole lifetime of the reader.
///
/// \param stream Source stream to read from
///
/// \return Properties of the loaded sound if the file was successfully opened
///
////////////////////////////////////////////////////////////
[[nodiscard]] virtual std::optional<Info> open(InputStream& stream) = 0;
////////////////////////////////////////////////////////////
/// \brief Change the current read position to the given sample offset
///
/// The sample offset takes the channels into account.
/// If you have a time offset instead, you can easily find
/// the corresponding sample offset with the following formula:
/// `timeInSeconds * sampleRate * channelCount`
/// If the given offset exceeds to total number of samples,
/// this function must jump to the end of the file.
///
/// \param sampleOffset Index of the sample to jump to, relative to the beginning
///
////////////////////////////////////////////////////////////
virtual void seek(std::uint64_t sampleOffset) = 0;
////////////////////////////////////////////////////////////
/// \brief Read audio samples from the open file
///
/// \param samples Pointer to the sample array to fill
/// \param maxCount Maximum number of samples to read
///
/// \return Number of samples actually read (may be less than \a maxCount)
///
////////////////////////////////////////////////////////////
[[nodiscard]] virtual std::uint64_t read(std::int16_t* samples, std::uint64_t maxCount) = 0;
};
} // namespace sf
////////////////////////////////////////////////////////////
/// \class sf::SoundFileReader
/// \ingroup audio
///
/// This class allows users to read audio file formats not natively
/// supported by SFML, and thus extend the set of supported readable
/// audio formats.
///
/// A valid sound file reader must override the open, seek and write functions,
/// as well as providing a static check function; the latter is used by
/// SFML to find a suitable writer for a given input file.
///
/// To register a new reader, use the `sf::SoundFileFactory::registerReader`
/// template function.
///
/// Usage example:
/// \code
/// class MySoundFileReader : public sf::SoundFileReader
/// {
/// public:
///
/// [[nodiscard]] static bool check(sf::InputStream& stream)
/// {
/// // typically, read the first few header bytes and check fields that identify the format
/// // return true if the reader can handle the format
/// }
///
/// [[nodiscard]] std::optional<sf::SoundFileReader::Info> open(sf::InputStream& stream) override
/// {
/// // read the sound file header and fill the sound attributes
/// // (channel count, sample count and sample rate)
/// // return true on success
/// }
///
/// void seek(std::uint64_t sampleOffset) override
/// {
/// // advance to the sampleOffset-th sample from the beginning of the
/// sound
/// }
///
/// std::uint64_t read(std::int16_t* samples, std::uint64_t maxCount) override
/// {
/// // read up to 'maxCount' samples into the 'samples' array,
/// // convert them (for example from normalized float) if they are not stored
/// // as 16-bits signed integers in the file
/// // return the actual number of samples read
/// }
/// };
///
/// sf::SoundFileFactory::registerReader<MySoundFileReader>();
/// \endcode
///
/// \see `sf::InputSoundFile`, `sf::SoundFileFactory`, `sf::SoundFileWriter`
///
////////////////////////////////////////////////////////////

View File

@ -1,130 +0,0 @@
////////////////////////////////////////////////////////////
//
// SFML - Simple and Fast Multimedia Library
// Copyright (C) 2007-2025 Laurent Gomila (laurent@sfml-dev.org)
//
// This software is provided 'as-is', without any express or implied warranty.
// In no event will the authors be held liable for any damages arising from the use of this software.
//
// Permission is granted to anyone to use this software for any purpose,
// including commercial applications, and to alter it and redistribute it freely,
// subject to the following restrictions:
//
// 1. The origin of this software must not be misrepresented;
// you must not claim that you wrote the original software.
// If you use this software in a product, an acknowledgment
// in the product documentation would be appreciated but is not required.
//
// 2. Altered source versions must be plainly marked as such,
// and must not be misrepresented as being the original software.
//
// 3. This notice may not be removed or altered from any source distribution.
//
////////////////////////////////////////////////////////////
#pragma once
////////////////////////////////////////////////////////////
// Headers
////////////////////////////////////////////////////////////
#include <SFML/Audio/Export.hpp>
#include <SFML/Audio/SoundChannel.hpp>
#include <filesystem>
#include <vector>
#include <cstdint>
namespace sf
{
////////////////////////////////////////////////////////////
/// \brief Abstract base class for sound file encoding
///
////////////////////////////////////////////////////////////
class SFML_AUDIO_API SoundFileWriter
{
public:
////////////////////////////////////////////////////////////
/// \brief Virtual destructor
///
////////////////////////////////////////////////////////////
virtual ~SoundFileWriter() = default;
////////////////////////////////////////////////////////////
/// \brief Open a sound file for writing
///
/// \param filename Path of the file to open
/// \param sampleRate Sample rate of the sound
/// \param channelCount Number of channels of the sound
/// \param channelMap Map of position in sample frame to sound channel
///
/// \return `true` if the file was successfully opened
///
////////////////////////////////////////////////////////////
[[nodiscard]] virtual bool open(const std::filesystem::path& filename,
unsigned int sampleRate,
unsigned int channelCount,
const std::vector<SoundChannel>& channelMap) = 0;
////////////////////////////////////////////////////////////
/// \brief Write audio samples to the open file
///
/// \param samples Pointer to the sample array to write
/// \param count Number of samples to write
///
////////////////////////////////////////////////////////////
virtual void write(const std::int16_t* samples, std::uint64_t count) = 0;
};
} // namespace sf
////////////////////////////////////////////////////////////
/// \class sf::SoundFileWriter
/// \ingroup audio
///
/// This class allows users to write audio file formats not natively
/// supported by SFML, and thus extend the set of supported writable
/// audio formats.
///
/// A valid sound file writer must override the open and write functions,
/// as well as providing a static check function; the latter is used by
/// SFML to find a suitable writer for a given filename.
///
/// To register a new writer, use the `sf::SoundFileFactory::registerWriter`
/// template function.
///
/// Usage example:
/// \code
/// class MySoundFileWriter : public sf::SoundFileWriter
/// {
/// public:
///
/// [[nodiscard]] static bool check(const std::filesystem::path& filename)
/// {
/// // typically, check the extension
/// // return true if the writer can handle the format
/// }
///
/// [[nodiscard]] bool open(const std::filesystem::path& filename, unsigned int sampleRate, unsigned int channelCount, const std::vector<SoundChannel>& channelMap) override
/// {
/// // open the file 'filename' for writing,
/// // write the given sample rate and channel count to the file header
/// // return true on success
/// }
///
/// void write(const std::int16_t* samples, std::uint64_t count) override
/// {
/// // write 'count' samples stored at address 'samples',
/// // convert them (for example to normalized float) if the format requires it
/// }
/// };
///
/// sf::SoundFileFactory::registerWriter<MySoundFileWriter>();
/// \endcode
///
/// \see `sf::OutputSoundFile`, `sf::SoundFileFactory`, `sf::SoundFileReader`
///
////////////////////////////////////////////////////////////

View File

@ -1,362 +0,0 @@
////////////////////////////////////////////////////////////
//
// SFML - Simple and Fast Multimedia Library
// Copyright (C) 2007-2025 Laurent Gomila (laurent@sfml-dev.org)
//
// This software is provided 'as-is', without any express or implied warranty.
// In no event will the authors be held liable for any damages arising from the use of this software.
//
// Permission is granted to anyone to use this software for any purpose,
// including commercial applications, and to alter it and redistribute it freely,
// subject to the following restrictions:
//
// 1. The origin of this software must not be misrepresented;
// you must not claim that you wrote the original software.
// If you use this software in a product, an acknowledgment
// in the product documentation would be appreciated but is not required.
//
// 2. Altered source versions must be plainly marked as such,
// and must not be misrepresented as being the original software.
//
// 3. This notice may not be removed or altered from any source distribution.
//
////////////////////////////////////////////////////////////
#pragma once
////////////////////////////////////////////////////////////
// Headers
////////////////////////////////////////////////////////////
#include <SFML/Audio/Export.hpp>
#include <SFML/Audio/SoundChannel.hpp>
#include <memory>
#include <string>
#include <vector>
#include <cstddef>
#include <cstdint>
namespace sf
{
////////////////////////////////////////////////////////////
/// \brief Abstract base class for capturing sound data
///
////////////////////////////////////////////////////////////
class SFML_AUDIO_API SoundRecorder
{
public:
////////////////////////////////////////////////////////////
/// \brief destructor
///
////////////////////////////////////////////////////////////
virtual ~SoundRecorder();
////////////////////////////////////////////////////////////
/// \brief Start the capture
///
/// The `sampleRate` parameter defines the number of audio samples
/// captured per second. The higher, the better the quality
/// (for example, 44100 samples/sec is CD quality).
/// This function uses its own thread so that it doesn't block
/// the rest of the program while the capture runs.
/// Please note that only one capture can happen at the same time.
/// You can select which capture device will be used by passing
/// the name to the `setDevice()` method. If none was selected
/// before, the default capture device will be used. You can get a
/// list of the names of all available capture devices by calling
/// `getAvailableDevices()`.
///
/// \param sampleRate Desired capture rate, in number of samples per second
///
/// \return `true`, if start of capture was successful
///
/// \see `stop`, `getAvailableDevices`
///
////////////////////////////////////////////////////////////
[[nodiscard]] bool start(unsigned int sampleRate = 44100);
////////////////////////////////////////////////////////////
/// \brief Stop the capture
///
/// \see `start`
///
////////////////////////////////////////////////////////////
void stop();
////////////////////////////////////////////////////////////
/// \brief Get the sample rate
///
/// The sample rate defines the number of audio samples
/// captured per second. The higher, the better the quality
/// (for example, 44100 samples/sec is CD quality).
///
/// \return Sample rate, in samples per second
///
////////////////////////////////////////////////////////////
[[nodiscard]] unsigned int getSampleRate() const;
////////////////////////////////////////////////////////////
/// \brief Get a list of the names of all available audio capture devices
///
/// This function returns a vector of strings, containing
/// the names of all available audio capture devices.
///
/// \return A vector of strings containing the names
///
////////////////////////////////////////////////////////////
[[nodiscard]] static std::vector<std::string> getAvailableDevices();
////////////////////////////////////////////////////////////
/// \brief Get the name of the default audio capture device
///
/// This function returns the name of the default audio
/// capture device. If none is available, an empty string
/// is returned.
///
/// \return The name of the default audio capture device
///
////////////////////////////////////////////////////////////
[[nodiscard]] static std::string getDefaultDevice();
////////////////////////////////////////////////////////////
/// \brief Set the audio capture device
///
/// This function sets the audio capture device to the device
/// with the given `name`. It can be called on the fly (i.e:
/// while recording). If you do so while recording and
/// opening the device fails, it stops the recording.
///
/// \param name The name of the audio capture device
///
/// \return `true`, if it was able to set the requested device
///
/// \see `getAvailableDevices`, `getDefaultDevice`
///
////////////////////////////////////////////////////////////
[[nodiscard]] bool setDevice(const std::string& name);
////////////////////////////////////////////////////////////
/// \brief Get the name of the current audio capture device
///
/// \return The name of the current audio capture device
///
////////////////////////////////////////////////////////////
[[nodiscard]] const std::string& getDevice() const;
////////////////////////////////////////////////////////////
/// \brief Set the channel count of the audio capture device
///
/// This method allows you to specify the number of channels
/// used for recording. Currently only 16-bit mono and
/// 16-bit stereo are supported.
///
/// \param channelCount Number of channels. Currently only
/// mono (1) and stereo (2) are supported.
///
/// \see `getChannelCount`
///
////////////////////////////////////////////////////////////
void setChannelCount(unsigned int channelCount);
////////////////////////////////////////////////////////////
/// \brief Get the number of channels used by this recorder
///
/// Currently only mono and stereo are supported, so the
/// value is either 1 (for mono) or 2 (for stereo).
///
/// \return Number of channels
///
/// \see `setChannelCount`
///
////////////////////////////////////////////////////////////
[[nodiscard]] unsigned int getChannelCount() const;
////////////////////////////////////////////////////////////
/// \brief Get the map of position in sample frame to sound channel
///
/// This is used to map a sample in the sample stream to a
/// position during spatialization.
///
/// \return Map of position in sample frame to sound channel
///
////////////////////////////////////////////////////////////
[[nodiscard]] const std::vector<SoundChannel>& getChannelMap() const;
////////////////////////////////////////////////////////////
/// \brief Check if the system supports audio capture
///
/// This function should always be called before using
/// the audio capture features. If it returns `false`, then
/// any attempt to use `sf::SoundRecorder` or one of its derived
/// classes will fail.
///
/// \return `true` if audio capture is supported, `false` otherwise
///
////////////////////////////////////////////////////////////
[[nodiscard]] static bool isAvailable();
protected:
////////////////////////////////////////////////////////////
/// \brief Default constructor
///
/// This constructor is only meant to be called by derived classes.
///
////////////////////////////////////////////////////////////
SoundRecorder();
////////////////////////////////////////////////////////////
/// \brief Start capturing audio data
///
/// This virtual function may be overridden by a derived class
/// if something has to be done every time a new capture
/// starts. If not, this function can be ignored; the default
/// implementation does nothing.
///
/// \return `true` to start the capture, or `false` to abort it
///
////////////////////////////////////////////////////////////
virtual bool onStart();
////////////////////////////////////////////////////////////
/// \brief Process a new chunk of recorded samples
///
/// This virtual function is called every time a new chunk of
/// recorded data is available. The derived class can then do
/// whatever it wants with it (storing it, playing it, sending
/// it over the network, etc.).
///
/// \param samples Pointer to the new chunk of recorded samples
/// \param sampleCount Number of samples pointed by `samples`
///
/// \return `true` to continue the capture, or `false` to stop it
///
////////////////////////////////////////////////////////////
[[nodiscard]] virtual bool onProcessSamples(const std::int16_t* samples, std::size_t sampleCount) = 0;
////////////////////////////////////////////////////////////
/// \brief Stop capturing audio data
///
/// This virtual function may be overridden by a derived class
/// if something has to be done every time the capture
/// ends. If not, this function can be ignored; the default
/// implementation does nothing.
///
////////////////////////////////////////////////////////////
virtual void onStop();
private:
////////////////////////////////////////////////////////////
// Member data
////////////////////////////////////////////////////////////
struct Impl;
const std::unique_ptr<Impl> m_impl; //!< Implementation details
};
} // namespace sf
////////////////////////////////////////////////////////////
/// \class sf::SoundRecorder
/// \ingroup audio
///
/// `sf::SoundBuffer` provides a simple interface to access
/// the audio recording capabilities of the computer
/// (the microphone). As an abstract base class, it only cares
/// about capturing sound samples, the task of making something
/// useful with them is left to the derived class. Note that
/// SFML provides a built-in specialization for saving the
/// captured data to a sound buffer (see `sf::SoundBufferRecorder`).
///
/// A derived class has only one virtual function to override:
/// \li `onProcessSamples` provides the new chunks of audio samples while the capture happens
///
/// Moreover, two additional virtual functions can be overridden
/// as well if necessary:
/// \li `onStart` is called before the capture happens, to perform custom initializations
/// \li `onStop` is called after the capture ends, to perform custom cleanup
///
/// The audio capture feature may not be supported or activated
/// on every platform, thus it is recommended to check its
/// availability with the isAvailable() function. If it returns
/// `false`, then any attempt to use an audio recorder will fail.
///
/// If you have multiple sound input devices connected to your
/// computer (for example: microphone, external sound card, webcam mic, ...)
/// you can get a list of all available devices through the
/// `getAvailableDevices()` function. You can then select a device
/// by calling `setDevice()` with the appropriate device. Otherwise
/// the default capturing device will be used.
///
/// By default the recording is in 16-bit mono. Using the
/// setChannelCount method you can change the number of channels
/// used by the audio capture device to record. Note that you
/// have to decide whether you want to record in mono or stereo
/// before starting the recording.
///
/// It is important to note that the audio capture happens in a
/// separate thread, so that it doesn't block the rest of the
/// program. In particular, the `onProcessSamples` virtual function
/// (but not `onStart` and not `onStop`) will be called
/// from this separate thread. It is important to keep this in
/// mind, because you may have to take care of synchronization
/// issues if you share data between threads.
/// Another thing to bear in mind is that you must call `stop()`
/// in the destructor of your derived class, so that the recording
/// thread finishes before your object is destroyed.
///
/// Usage example:
/// \code
/// class CustomRecorder : public sf::SoundRecorder
/// {
/// public:
/// ~CustomRecorder()
/// {
/// // Make sure to stop the recording thread
/// stop();
/// }
///
/// private:
/// bool onStart() override // optional
/// {
/// // Initialize whatever has to be done before the capture starts
/// ...
///
/// // Return true to start playing
/// return true;
/// }
///
/// [[nodiscard]] bool onProcessSamples(const std::int16_t* samples, std::size_t sampleCount) override
/// {
/// // Do something with the new chunk of samples (store them, send them, ...)
/// ...
///
/// // Return true to continue playing
/// return true;
/// }
///
/// void onStop() override // optional
/// {
/// // Clean up whatever has to be done after the capture ends
/// ...
/// }
/// };
///
/// // Usage
/// if (CustomRecorder::isAvailable())
/// {
/// CustomRecorder recorder;
///
/// if (!recorder.start())
/// return -1;
///
/// ...
/// recorder.stop();
/// }
/// \endcode
///
/// \see `sf::SoundBufferRecorder`
///
////////////////////////////////////////////////////////////

View File

@ -1,686 +0,0 @@
////////////////////////////////////////////////////////////
//
// SFML - Simple and Fast Multimedia Library
// Copyright (C) 2007-2025 Laurent Gomila (laurent@sfml-dev.org)
//
// This software is provided 'as-is', without any express or implied warranty.
// In no event will the authors be held liable for any damages arising from the use of this software.
//
// Permission is granted to anyone to use this software for any purpose,
// including commercial applications, and to alter it and redistribute it freely,
// subject to the following restrictions:
//
// 1. The origin of this software must not be misrepresented;
// you must not claim that you wrote the original software.
// If you use this software in a product, an acknowledgment
// in the product documentation would be appreciated but is not required.
//
// 2. Altered source versions must be plainly marked as such,
// and must not be misrepresented as being the original software.
//
// 3. This notice may not be removed or altered from any source distribution.
//
////////////////////////////////////////////////////////////
#pragma once
////////////////////////////////////////////////////////////
// Headers
////////////////////////////////////////////////////////////
#include <SFML/Audio/Export.hpp>
#include <SFML/Audio/AudioResource.hpp>
#include <SFML/System/Angle.hpp>
#include <SFML/System/Vector3.hpp>
#include <functional>
namespace sf
{
// NOLINTBEGIN(readability-make-member-function-const)
////////////////////////////////////////////////////////////
/// \brief Base class defining a sound's properties
///
////////////////////////////////////////////////////////////
class SFML_AUDIO_API SoundSource : protected AudioResource
{
public:
////////////////////////////////////////////////////////////
/// \brief Enumeration of the sound source states
///
////////////////////////////////////////////////////////////
enum class Status
{
Stopped, //!< Sound is not playing
Paused, //!< Sound is paused
Playing //!< Sound is playing
};
////////////////////////////////////////////////////////////
/// \brief Structure defining the properties of a directional cone
///
/// Sounds will play at gain 1 when the listener
/// is positioned within the inner angle of the cone.
/// Sounds will play at `outerGain` when the listener is
/// positioned outside the outer angle of the cone.
/// The gain declines linearly from 1 to `outerGain` as the
/// listener moves from the inner angle to the outer angle.
///
////////////////////////////////////////////////////////////
struct Cone
{
Angle innerAngle; //!< Inner angle
Angle outerAngle; //!< Outer angle
float outerGain{}; //!< Outer gain
};
////////////////////////////////////////////////////////////
/// \brief Callable that is provided with sound data for processing
///
/// When the audio engine sources sound data from sound
/// sources it will pass the data through an effects
/// processor if one is set. The sound data will already be
/// converted to the internal floating point format.
///
/// Sound data that is processed this way is provided in
/// frames. Each frame contains 1 floating point sample per
/// channel. If e.g. the data source provides stereo data,
/// each frame will contain 2 floats.
///
/// The effects processor function takes 4 parameters:
/// - The input data frames, channels interleaved
/// - The number of input data frames available
/// - The buffer to write output data frames to, channels interleaved
/// - The number of output data frames that the output buffer can hold
/// - The channel count
///
/// The input and output frame counts are in/out parameters.
///
/// When this function is called, the input count will
/// contain the number of frames available in the input
/// buffer. The output count will contain the size of the
/// output buffer i.e. the maximum number of frames that
/// can be written to the output buffer.
///
/// Attempting to read more frames than the input frame
/// count or write more frames than the output frame count
/// will result in undefined behaviour.
///
/// It is important to note that the channel count of the
/// audio engine currently sourcing data from this sound
/// will always be provided in `frameChannelCount`. This can
/// be different from the channel count of the sound source
/// so make sure to size necessary processing buffers
/// according to the engine channel count and not the sound
/// source channel count.
///
/// When done processing the frames, the input and output
/// frame counts must be updated to reflect the actual
/// number of frames that were read from the input and
/// written to the output.
///
/// The processing function should always try to process as
/// much sound data as possible i.e. always try to fill the
/// output buffer to the maximum. In certain situations for
/// specific effects it can be possible that the input frame
/// count and output frame count aren't equal. As long as
/// the frame counts are updated accordingly this is
/// perfectly valid.
///
/// If the audio engine determines that no audio data is
/// available from the data source, the input data frames
/// pointer is set to `nullptr` and the input frame count is
/// set to 0. In this case it is up to the function to
/// decide how to handle the situation. For specific effects
/// e.g. Echo/Delay buffered data might still be able to be
/// written to the output buffer even if there is no longer
/// any input data.
///
/// An important thing to remember is that this function is
/// directly called by the audio engine. Because the audio
/// engine runs on an internal thread of its own, make sure
/// access to shared data is synchronized appropriately.
///
/// Because this function is stored by the `SoundSource`
/// object it will be able to be called as long as the
/// `SoundSource` object hasn't yet been destroyed. Make sure
/// that any data this function references outlives the
/// SoundSource object otherwise use-after-free errors will
/// occur.
///
////////////////////////////////////////////////////////////
using EffectProcessor = std::function<
void(const float* inputFrames, unsigned int& inputFrameCount, float* outputFrames, unsigned int& outputFrameCount, unsigned int frameChannelCount)>;
////////////////////////////////////////////////////////////
/// \brief Copy constructor
///
////////////////////////////////////////////////////////////
SoundSource(const SoundSource&) = default;
////////////////////////////////////////////////////////////
/// \brief Move constructor
///
////////////////////////////////////////////////////////////
SoundSource(SoundSource&&) noexcept = default;
////////////////////////////////////////////////////////////
/// \brief Move assignment
///
////////////////////////////////////////////////////////////
SoundSource& operator=(SoundSource&&) noexcept = default;
////////////////////////////////////////////////////////////
/// \brief Destructor
///
////////////////////////////////////////////////////////////
virtual ~SoundSource() = default;
////////////////////////////////////////////////////////////
/// \brief Set the pitch of the sound
///
/// The pitch represents the perceived fundamental frequency
/// of a sound; thus you can make a sound more acute or grave
/// by changing its pitch. A side effect of changing the pitch
/// is to modify the playing speed of the sound as well.
/// The default value for the pitch is 1.
///
/// \param pitch New pitch to apply to the sound
///
/// \see `getPitch`
///
////////////////////////////////////////////////////////////
void setPitch(float pitch);
////////////////////////////////////////////////////////////
/// \brief Set the pan of the sound
///
/// Using panning, a mono sound can be panned between
/// stereo channels. When the pan is set to -1, the sound
/// is played only on the left channel, when the pan is set
/// to +1, the sound is played only on the right channel.
///
/// \param pan New pan to apply to the sound [-1, +1]
///
/// \see `getPan`
///
////////////////////////////////////////////////////////////
void setPan(float pan);
////////////////////////////////////////////////////////////
/// \brief Set the volume of the sound
///
/// The volume is a value between 0 (mute) and 100 (full volume).
/// The default value for the volume is 100.
///
/// \param volume Volume of the sound
///
/// \see `getVolume`
///
////////////////////////////////////////////////////////////
void setVolume(float volume);
////////////////////////////////////////////////////////////
/// \brief Set whether spatialization of the sound is enabled
///
/// Spatialization is the application of various effects to
/// simulate a sound being emitted at a virtual position in
/// 3D space and exhibiting various physical phenomena such as
/// directional attenuation and doppler shift.
///
/// \param enabled `true` to enable spatialization, `false` to disable
///
/// \see `isSpatializationEnabled`
///
////////////////////////////////////////////////////////////
void setSpatializationEnabled(bool enabled);
////////////////////////////////////////////////////////////
/// \brief Set the 3D position of the sound in the audio scene
///
/// Only sounds with one channel (mono sounds) can be
/// spatialized.
/// The default position of a sound is (0, 0, 0).
///
/// \param position Position of the sound in the scene
///
/// \see `getPosition`
///
////////////////////////////////////////////////////////////
void setPosition(const Vector3f& position);
////////////////////////////////////////////////////////////
/// \brief Set the 3D direction of the sound in the audio scene
///
/// The direction defines where the sound source is facing
/// in 3D space. It will affect how the sound is attenuated
/// if facing away from the listener.
/// The default direction of a sound is (0, 0, -1).
///
/// \param direction Direction of the sound in the scene
///
/// \see `getDirection`
///
////////////////////////////////////////////////////////////
void setDirection(const Vector3f& direction);
////////////////////////////////////////////////////////////
/// \brief Set the cone properties of the sound in the audio scene
///
/// The cone defines how directional attenuation is applied.
/// The default cone of a sound is (2 * PI, 2 * PI, 1).
///
/// \param cone Cone properties of the sound in the scene
///
/// \see `getCone`
///
////////////////////////////////////////////////////////////
void setCone(const Cone& cone);
////////////////////////////////////////////////////////////
/// \brief Set the 3D velocity of the sound in the audio scene
///
/// The velocity is used to determine how to doppler shift
/// the sound. Sounds moving towards the listener will be
/// perceived to have a higher pitch and sounds moving away
/// from the listener will be perceived to have a lower pitch.
///
/// \param velocity Velocity of the sound in the scene
///
/// \see `getVelocity`
///
////////////////////////////////////////////////////////////
void setVelocity(const Vector3f& velocity);
////////////////////////////////////////////////////////////
/// \brief Set the doppler factor of the sound
///
/// The doppler factor determines how strong the doppler
/// shift will be.
///
/// \param factor New doppler factor to apply to the sound
///
/// \see `getDopplerFactor`
///
////////////////////////////////////////////////////////////
void setDopplerFactor(float factor);
////////////////////////////////////////////////////////////
/// \brief Set the directional attenuation factor of the sound
///
/// Depending on the virtual position of an output channel
/// relative to the listener (such as in surround sound
/// setups), sounds will be attenuated when emitting them
/// from certain channels. This factor determines how strong
/// the attenuation based on output channel position
/// relative to the listener is.
///
/// \param factor New directional attenuation factor to apply to the sound
///
/// \see `getDirectionalAttenuationFactor`
///
////////////////////////////////////////////////////////////
void setDirectionalAttenuationFactor(float factor);
////////////////////////////////////////////////////////////
/// \brief Make the sound's position relative to the listener or absolute
///
/// Making a sound relative to the listener will ensure that it will always
/// be played the same way regardless of the position of the listener.
/// This can be useful for non-spatialized sounds, sounds that are
/// produced by the listener, or sounds attached to it.
/// The default value is `false` (position is absolute).
///
/// \param relative `true` to set the position relative, `false` to set it absolute
///
/// \see `isRelativeToListener`
///
////////////////////////////////////////////////////////////
void setRelativeToListener(bool relative);
////////////////////////////////////////////////////////////
/// \brief Set the minimum distance of the sound
///
/// The "minimum distance" of a sound is the maximum
/// distance at which it is heard at its maximum volume. Further
/// than the minimum distance, it will start to fade out according
/// to its attenuation factor. A value of 0 ("inside the head
/// of the listener") is an invalid value and is forbidden.
/// The default value of the minimum distance is 1.
///
/// \param distance New minimum distance of the sound
///
/// \see `getMinDistance`, `setAttenuation`
///
////////////////////////////////////////////////////////////
void setMinDistance(float distance);
////////////////////////////////////////////////////////////
/// \brief Set the maximum distance of the sound
///
/// The "maximum distance" of a sound is the minimum
/// distance at which it is heard at its minimum volume. Closer
/// than the maximum distance, it will start to fade in according
/// to its attenuation factor.
/// The default value of the maximum distance is the maximum
/// value a float can represent.
///
/// \param distance New maximum distance of the sound
///
/// \see `getMaxDistance`, `setAttenuation`
///
////////////////////////////////////////////////////////////
void setMaxDistance(float distance);
////////////////////////////////////////////////////////////
/// \brief Set the minimum gain of the sound
///
/// When the sound is further away from the listener than
/// the "maximum distance" the attenuated gain is clamped
/// so it cannot go below the minimum gain value.
///
/// \param gain New minimum gain of the sound
///
/// \see `getMinGain`, `setAttenuation`
///
////////////////////////////////////////////////////////////
void setMinGain(float gain);
////////////////////////////////////////////////////////////
/// \brief Set the maximum gain of the sound
///
/// When the sound is closer from the listener than
/// the "minimum distance" the attenuated gain is clamped
/// so it cannot go above the maximum gain value.
///
/// \param gain New maximum gain of the sound
///
/// \see `getMaxGain`, `setAttenuation`
///
////////////////////////////////////////////////////////////
void setMaxGain(float gain);
////////////////////////////////////////////////////////////
/// \brief Set the attenuation factor of the sound
///
/// The attenuation is a multiplicative factor which makes
/// the sound more or less loud according to its distance
/// from the listener. An attenuation of 0 will produce a
/// non-attenuated sound, i.e. its volume will always be the same
/// whether it is heard from near or from far. On the other hand,
/// an attenuation value such as 100 will make the sound fade out
/// very quickly as it gets further from the listener.
/// The default value of the attenuation is 1.
///
/// \param attenuation New attenuation factor of the sound
///
/// \see `getAttenuation`, `setMinDistance`
///
////////////////////////////////////////////////////////////
void setAttenuation(float attenuation);
////////////////////////////////////////////////////////////
/// \brief Set the effect processor to be applied to the sound
///
/// The effect processor is a callable that will be called
/// with sound data to be processed.
///
/// \param effectProcessor The effect processor to attach to this sound, attach an empty processor to disable processing
///
////////////////////////////////////////////////////////////
virtual void setEffectProcessor(EffectProcessor effectProcessor);
////////////////////////////////////////////////////////////
/// \brief Get the pitch of the sound
///
/// \return Pitch of the sound
///
/// \see `setPitch`
///
////////////////////////////////////////////////////////////
[[nodiscard]] float getPitch() const;
////////////////////////////////////////////////////////////
/// \brief Get the pan of the sound
///
/// \return Pan of the sound
///
/// \see `setPan`
///
////////////////////////////////////////////////////////////
[[nodiscard]] float getPan() const;
////////////////////////////////////////////////////////////
/// \brief Get the volume of the sound
///
/// \return Volume of the sound, in the range [0, 100]
///
/// \see `setVolume`
///
////////////////////////////////////////////////////////////
[[nodiscard]] float getVolume() const;
////////////////////////////////////////////////////////////
/// \brief Tell whether spatialization of the sound is enabled
///
/// \return `true` if spatialization is enabled, `false` if it's disabled
///
/// \see `setSpatializationEnabled`
///
////////////////////////////////////////////////////////////
[[nodiscard]] bool isSpatializationEnabled() const;
////////////////////////////////////////////////////////////
/// \brief Get the 3D position of the sound in the audio scene
///
/// \return Position of the sound
///
/// \see `setPosition`
///
////////////////////////////////////////////////////////////
[[nodiscard]] Vector3f getPosition() const;
////////////////////////////////////////////////////////////
/// \brief Get the 3D direction of the sound in the audio scene
///
/// \return Direction of the sound
///
/// \see `setDirection`
///
////////////////////////////////////////////////////////////
[[nodiscard]] Vector3f getDirection() const;
////////////////////////////////////////////////////////////
/// \brief Get the cone properties of the sound in the audio scene
///
/// \return Cone properties of the sound
///
/// \see `setCone`
///
////////////////////////////////////////////////////////////
[[nodiscard]] Cone getCone() const;
////////////////////////////////////////////////////////////
/// \brief Get the 3D velocity of the sound in the audio scene
///
/// \return Velocity of the sound
///
/// \see `setVelocity`
///
////////////////////////////////////////////////////////////
[[nodiscard]] Vector3f getVelocity() const;
////////////////////////////////////////////////////////////
/// \brief Get the doppler factor of the sound
///
/// \return Doppler factor of the sound
///
/// \see `setDopplerFactor`
///
////////////////////////////////////////////////////////////
[[nodiscard]] float getDopplerFactor() const;
////////////////////////////////////////////////////////////
/// \brief Get the directional attenuation factor of the sound
///
/// \return Directional attenuation factor of the sound
///
/// \see `setDirectionalAttenuationFactor`
///
////////////////////////////////////////////////////////////
[[nodiscard]] float getDirectionalAttenuationFactor() const;
////////////////////////////////////////////////////////////
/// \brief Tell whether the sound's position is relative to the
/// listener or is absolute
///
/// \return `true` if the position is relative, `false` if it's absolute
///
/// \see `setRelativeToListener`
///
////////////////////////////////////////////////////////////
[[nodiscard]] bool isRelativeToListener() const;
////////////////////////////////////////////////////////////
/// \brief Get the minimum distance of the sound
///
/// \return Minimum distance of the sound
///
/// \see `setMinDistance`, `getAttenuation`
///
////////////////////////////////////////////////////////////
[[nodiscard]] float getMinDistance() const;
////////////////////////////////////////////////////////////
/// \brief Get the maximum distance of the sound
///
/// \return Maximum distance of the sound
///
/// \see `setMaxDistance`, `getAttenuation`
///
////////////////////////////////////////////////////////////
[[nodiscard]] float getMaxDistance() const;
////////////////////////////////////////////////////////////
/// \brief Get the minimum gain of the sound
///
/// \return Minimum gain of the sound
///
/// \see `setMinGain`, `getAttenuation`
///
////////////////////////////////////////////////////////////
[[nodiscard]] float getMinGain() const;
////////////////////////////////////////////////////////////
/// \brief Get the maximum gain of the sound
///
/// \return Maximum gain of the sound
///
/// \see `setMaxGain`, `getAttenuation`
///
////////////////////////////////////////////////////////////
[[nodiscard]] float getMaxGain() const;
////////////////////////////////////////////////////////////
/// \brief Get the attenuation factor of the sound
///
/// \return Attenuation factor of the sound
///
/// \see `setAttenuation`, `getMinDistance`
///
////////////////////////////////////////////////////////////
[[nodiscard]] float getAttenuation() const;
////////////////////////////////////////////////////////////
/// \brief Overload of assignment operator
///
/// \param right Instance to assign
///
/// \return Reference to self
///
////////////////////////////////////////////////////////////
SoundSource& operator=(const SoundSource& right);
////////////////////////////////////////////////////////////
/// \brief Start or resume playing the sound source
///
/// This function starts the source if it was stopped, resumes
/// it if it was paused, and restarts it from the beginning if
/// it was already playing.
///
/// \see `pause`, `stop`
///
////////////////////////////////////////////////////////////
virtual void play() = 0;
////////////////////////////////////////////////////////////
/// \brief Pause the sound source
///
/// This function pauses the source if it was playing,
/// otherwise (source already paused or stopped) it has no effect.
///
/// \see `play`, `stop`
///
////////////////////////////////////////////////////////////
virtual void pause() = 0;
////////////////////////////////////////////////////////////
/// \brief Stop playing the sound source
///
/// This function stops the source if it was playing or paused,
/// and does nothing if it was already stopped.
/// It also resets the playing position (unlike `pause()`).
///
/// \see `play`, `pause`
///
////////////////////////////////////////////////////////////
virtual void stop() = 0;
////////////////////////////////////////////////////////////
/// \brief Get the current status of the sound (stopped, paused, playing)
///
/// \return Current status of the sound
///
////////////////////////////////////////////////////////////
[[nodiscard]] virtual Status getStatus() const = 0;
protected:
////////////////////////////////////////////////////////////
/// \brief Default constructor
///
/// This constructor is meant to be called by derived classes only.
///
////////////////////////////////////////////////////////////
SoundSource() = default;
private:
////////////////////////////////////////////////////////////
/// \brief Get the sound object
///
/// \return The sound object
///
////////////////////////////////////////////////////////////
[[nodiscard]] virtual void* getSound() const = 0;
};
// NOLINTEND(readability-make-member-function-const)
} // namespace sf
////////////////////////////////////////////////////////////
/// \class sf::SoundSource
/// \ingroup audio
///
/// `sf::SoundSource` is not meant to be used directly, it
/// only serves as a common base for all audio objects
/// that can live in the audio environment.
///
/// It defines several properties for the sound: pitch,
/// volume, position, attenuation, etc. All of them can be
/// changed at any time with no impact on performances.
///
/// \see `sf::Sound`, `sf::SoundStream`
///
////////////////////////////////////////////////////////////

View File

@ -1,385 +0,0 @@
////////////////////////////////////////////////////////////
//
// SFML - Simple and Fast Multimedia Library
// Copyright (C) 2007-2025 Laurent Gomila (laurent@sfml-dev.org)
//
// This software is provided 'as-is', without any express or implied warranty.
// In no event will the authors be held liable for any damages arising from the use of this software.
//
// Permission is granted to anyone to use this software for any purpose,
// including commercial applications, and to alter it and redistribute it freely,
// subject to the following restrictions:
//
// 1. The origin of this software must not be misrepresented;
// you must not claim that you wrote the original software.
// If you use this software in a product, an acknowledgment
// in the product documentation would be appreciated but is not required.
//
// 2. Altered source versions must be plainly marked as such,
// and must not be misrepresented as being the original software.
//
// 3. This notice may not be removed or altered from any source distribution.
//
////////////////////////////////////////////////////////////
#pragma once
////////////////////////////////////////////////////////////
// Headers
////////////////////////////////////////////////////////////
#include <SFML/Audio/Export.hpp>
#include <SFML/Audio/SoundChannel.hpp>
#include <SFML/Audio/SoundSource.hpp>
#include <SFML/System/Time.hpp>
#include <memory>
#include <optional>
#include <vector>
#include <cstddef>
#include <cstdint>
namespace sf
{
////////////////////////////////////////////////////////////
/// \brief Abstract base class for streamed audio sources
///
////////////////////////////////////////////////////////////
class SFML_AUDIO_API SoundStream : public SoundSource
{
public:
////////////////////////////////////////////////////////////
/// \brief Structure defining a chunk of audio data to stream
///
////////////////////////////////////////////////////////////
struct Chunk
{
const std::int16_t* samples{}; //!< Pointer to the audio samples
std::size_t sampleCount{}; //!< Number of samples pointed by Samples
};
////////////////////////////////////////////////////////////
/// \brief Destructor
///
////////////////////////////////////////////////////////////
~SoundStream() override;
////////////////////////////////////////////////////////////
/// \brief Move constructor
///
////////////////////////////////////////////////////////////
SoundStream(SoundStream&&) noexcept;
////////////////////////////////////////////////////////////
/// \brief Move assignment
///
////////////////////////////////////////////////////////////
SoundStream& operator=(SoundStream&&) noexcept;
////////////////////////////////////////////////////////////
/// \brief Start or resume playing the audio stream
///
/// This function starts the stream if it was stopped, resumes
/// it if it was paused, and restarts it from the beginning if
/// it was already playing.
/// This function uses its own thread so that it doesn't block
/// the rest of the program while the stream is played.
///
/// \see `pause`, `stop`
///
////////////////////////////////////////////////////////////
void play() override;
////////////////////////////////////////////////////////////
/// \brief Pause the audio stream
///
/// This function pauses the stream if it was playing,
/// otherwise (stream already paused or stopped) it has no effect.
///
/// \see `play`, `stop`
///
////////////////////////////////////////////////////////////
void pause() override;
////////////////////////////////////////////////////////////
/// \brief Stop playing the audio stream
///
/// This function stops the stream if it was playing or paused,
/// and does nothing if it was already stopped.
/// It also resets the playing position (unlike `pause()`).
///
/// \see `play`, `pause`
///
////////////////////////////////////////////////////////////
void stop() override;
////////////////////////////////////////////////////////////
/// \brief Return the number of channels of the stream
///
/// 1 channel means a mono sound, 2 means stereo, etc.
///
/// \return Number of channels
///
////////////////////////////////////////////////////////////
[[nodiscard]] unsigned int getChannelCount() const;
////////////////////////////////////////////////////////////
/// \brief Get the stream sample rate of the stream
///
/// The sample rate is the number of audio samples played per
/// second. The higher, the better the quality.
///
/// \return Sample rate, in number of samples per second
///
////////////////////////////////////////////////////////////
[[nodiscard]] unsigned int getSampleRate() const;
////////////////////////////////////////////////////////////
/// \brief Get the map of position in sample frame to sound channel
///
/// This is used to map a sample in the sample stream to a
/// position during spatialization.
///
/// \return Map of position in sample frame to sound channel
///
////////////////////////////////////////////////////////////
[[nodiscard]] std::vector<SoundChannel> getChannelMap() const;
////////////////////////////////////////////////////////////
/// \brief Get the current status of the stream (stopped, paused, playing)
///
/// \return Current status
///
////////////////////////////////////////////////////////////
[[nodiscard]] Status getStatus() const override;
////////////////////////////////////////////////////////////
/// \brief Change the current playing position of the stream
///
/// The playing position can be changed when the stream is
/// either paused or playing. Changing the playing position
/// when the stream is stopped has no effect, since playing
/// the stream would reset its position.
///
/// \param timeOffset New playing position, from the beginning of the stream
///
/// \see `getPlayingOffset`
///
////////////////////////////////////////////////////////////
void setPlayingOffset(Time timeOffset);
////////////////////////////////////////////////////////////
/// \brief Get the current playing position of the stream
///
/// \return Current playing position, from the beginning of the stream
///
/// \see `setPlayingOffset`
///
////////////////////////////////////////////////////////////
[[nodiscard]] Time getPlayingOffset() const;
////////////////////////////////////////////////////////////
/// \brief Set whether or not the stream should loop after reaching the end
///
/// If set, the stream will restart from beginning after
/// reaching the end and so on, until it is stopped or
/// `setLooping(false)` is called.
/// The default looping state for streams is `false`.
///
/// \param loop `true` to play in loop, `false` to play once
///
/// \see `isLooping`
///
////////////////////////////////////////////////////////////
void setLooping(bool loop);
////////////////////////////////////////////////////////////
/// \brief Tell whether or not the stream is in loop mode
///
/// \return `true` if the stream is looping, `false` otherwise
///
/// \see `setLooping`
///
////////////////////////////////////////////////////////////
[[nodiscard]] bool isLooping() const;
////////////////////////////////////////////////////////////
/// \brief Set the effect processor to be applied to the sound
///
/// The effect processor is a callable that will be called
/// with sound data to be processed.
///
/// \param effectProcessor The effect processor to attach to this sound, attach an empty processor to disable processing
///
////////////////////////////////////////////////////////////
void setEffectProcessor(EffectProcessor effectProcessor) override;
protected:
////////////////////////////////////////////////////////////
/// \brief Default constructor
///
/// This constructor is only meant to be called by derived classes.
///
////////////////////////////////////////////////////////////
SoundStream();
////////////////////////////////////////////////////////////
/// \brief Define the audio stream parameters
///
/// This function must be called by derived classes as soon
/// as they know the audio settings of the stream to play.
/// Any attempt to manipulate the stream (`play()`, ...) before
/// calling this function will fail.
/// It can be called multiple times if the settings of the
/// audio stream change, but only when the stream is stopped.
///
/// \param channelCount Number of channels of the stream
/// \param sampleRate Sample rate, in samples per second
/// \param channelMap Map of position in sample frame to sound channel
///
////////////////////////////////////////////////////////////
void initialize(unsigned int channelCount, unsigned int sampleRate, const std::vector<SoundChannel>& channelMap);
////////////////////////////////////////////////////////////
/// \brief Request a new chunk of audio samples from the stream source
///
/// This function must be overridden by derived classes to provide
/// the audio samples to play. It is called continuously by the
/// streaming loop, in a separate thread.
/// The source can choose to stop the streaming loop at any time, by
/// returning `false` to the caller.
/// If you return `true` (i.e. continue streaming) it is important that
/// the returned array of samples is not empty; this would stop the stream
/// due to an internal limitation.
///
/// \param data Chunk of data to fill
///
/// \return `true` to continue playback, `false` to stop
///
////////////////////////////////////////////////////////////
[[nodiscard]] virtual bool onGetData(Chunk& data) = 0;
////////////////////////////////////////////////////////////
/// \brief Change the current playing position in the stream source
///
/// This function must be overridden by derived classes to
/// allow random seeking into the stream source.
///
/// \param timeOffset New playing position, relative to the beginning of the stream
///
////////////////////////////////////////////////////////////
virtual void onSeek(Time timeOffset) = 0;
////////////////////////////////////////////////////////////
/// \brief Change the current playing position in the stream source to the beginning of the loop
///
/// This function can be overridden by derived classes to
/// allow implementation of custom loop points. Otherwise,
/// it just calls `onSeek(Time::Zero)` and returns 0.
///
/// \return The seek position after looping (or `std::nullopt` if there's no loop)
///
////////////////////////////////////////////////////////////
virtual std::optional<std::uint64_t> onLoop();
private:
////////////////////////////////////////////////////////////
/// \brief Get the sound object
///
/// \return The sound object
///
////////////////////////////////////////////////////////////
[[nodiscard]] void* getSound() const override;
////////////////////////////////////////////////////////////
// Member data
////////////////////////////////////////////////////////////
struct Impl;
std::unique_ptr<Impl> m_impl; //!< Implementation details
};
} // namespace sf
////////////////////////////////////////////////////////////
/// \class sf::SoundStream
/// \ingroup audio
///
/// Unlike audio buffers (see `sf::SoundBuffer`), audio streams
/// are never completely loaded in memory. Instead, the audio
/// data is acquired continuously while the stream is playing.
/// This behavior allows to play a sound with no loading delay,
/// and keeps the memory consumption very low.
///
/// Sound sources that need to be streamed are usually big files
/// (compressed audio musics that would eat hundreds of MB in memory)
/// or files that would take a lot of time to be received
/// (sounds played over the network).
///
/// `sf::SoundStream` is a base class that doesn't care about the
/// stream source, which is left to the derived class. SFML provides
/// a built-in specialization for big files (see `sf::Music`).
/// No network stream source is provided, but you can write your own
/// by combining this class with the network module.
///
/// A derived class has to override two virtual functions:
/// \li `onGetData` fills a new chunk of audio data to be played
/// \li `onSeek` changes the current playing position in the source
///
/// It is important to note that each SoundStream is played in its
/// own separate thread, so that the streaming loop doesn't block the
/// rest of the program. In particular, the `onGetData` and `onSeek`
/// virtual functions may sometimes be called from this separate thread.
/// It is important to keep this in mind, because you may have to take
/// care of synchronization issues if you share data between threads.
///
/// Usage example:
/// \code
/// class CustomStream : public sf::SoundStream
/// {
/// public:
///
/// [[nodiscard]] bool open(const std::string& location)
/// {
/// // Open the source and get audio settings
/// ...
/// unsigned int channelCount = 2; // Stereo
/// unsigned int sampleRate = 44100; // 44100 Hz
///
/// // Initialize the stream -- important!
/// initialize(channelCount, sampleRate, {sf::SoundChannel::FrontLeft, sf::SoundChannel::FrontRight});
/// return true;
/// }
///
/// private:
///
/// bool onGetData(Chunk& data) override
/// {
/// // Fill the chunk with audio data from the stream source
/// // (note: must not be empty if you want to continue playing)
/// data.samples = ...;
///
/// // Return true to continue playing
/// data.sampleCount = ...;
/// return true;
/// }
///
/// void onSeek(sf::Time timeOffset) override
/// {
/// // Change the current position in the stream source
/// ...
/// }
/// };
///
/// // Usage
/// CustomStream stream;
/// stream.open("path/to/stream");
/// stream.play();
/// \endcode
///
/// \see `sf::Music`
///
////////////////////////////////////////////////////////////

View File

@ -1,164 +0,0 @@
////////////////////////////////////////////////////////////
//
// SFML - Simple and Fast Multimedia Library
// Copyright (C) 2007-2025 Laurent Gomila (laurent@sfml-dev.org)
//
// This software is provided 'as-is', without any express or implied warranty.
// In no event will the authors be held liable for any damages arising from the use of this software.
//
// Permission is granted to anyone to use this software for any purpose,
// including commercial applications, and to alter it and redistribute it freely,
// subject to the following restrictions:
//
// 1. The origin of this software must not be misrepresented;
// you must not claim that you wrote the original software.
// If you use this software in a product, an acknowledgment
// in the product documentation would be appreciated but is not required.
//
// 2. Altered source versions must be plainly marked as such,
// and must not be misrepresented as being the original software.
//
// 3. This notice may not be removed or altered from any source distribution.
//
////////////////////////////////////////////////////////////
#pragma once
////////////////////////////////////////////////////////////
// SFML version
////////////////////////////////////////////////////////////
#define SFML_VERSION_MAJOR 3
#define SFML_VERSION_MINOR 0
#define SFML_VERSION_PATCH 2
#define SFML_VERSION_IS_RELEASE true
////////////////////////////////////////////////////////////
// Identify the operating system
// see https://sourceforge.net/p/predef/wiki/Home/
////////////////////////////////////////////////////////////
#if defined(_WIN32)
// Windows
#define SFML_SYSTEM_WINDOWS
#ifndef NOMINMAX
#define NOMINMAX
#endif
#elif defined(__APPLE__) && defined(__MACH__)
// Apple platform, see which one it is
#include "TargetConditionals.h"
#if TARGET_OS_IPHONE || TARGET_IPHONE_SIMULATOR
// iOS
#define SFML_SYSTEM_IOS
#elif TARGET_OS_MAC
// macOS
#define SFML_SYSTEM_MACOS
#else
// Unsupported Apple system
#error This Apple operating system is not supported by SFML library
#endif
#elif defined(__unix__)
// UNIX system, see which one it is
#if defined(__ANDROID__)
// Android
#define SFML_SYSTEM_ANDROID
#elif defined(__linux__)
// Linux
#define SFML_SYSTEM_LINUX
#elif defined(__FreeBSD__) || defined(__FreeBSD_kernel__)
// FreeBSD
#define SFML_SYSTEM_FREEBSD
#elif defined(__OpenBSD__)
// OpenBSD
#define SFML_SYSTEM_OPENBSD
#elif defined(__NetBSD__)
// NetBSD
#define SFML_SYSTEM_NETBSD
#else
// Unsupported UNIX system
#error This UNIX operating system is not supported by SFML library
#endif
#else
// Unsupported system
#error This operating system is not supported by SFML library
#endif
////////////////////////////////////////////////////////////
// Ensure minimum C++ language standard version is met
////////////////////////////////////////////////////////////
#if (defined(_MSVC_LANG) && _MSVC_LANG < 201703L) || (!defined(_MSVC_LANG) && __cplusplus < 201703L)
#error "Enable C++17 or newer for your compiler (e.g. -std=c++17 for GCC/Clang or /std:c++17 for MSVC)"
#endif
////////////////////////////////////////////////////////////
// Portable debug macro
////////////////////////////////////////////////////////////
#if !defined(NDEBUG)
#define SFML_DEBUG
#endif
////////////////////////////////////////////////////////////
// Helpers to create portable import / export macros for each module
////////////////////////////////////////////////////////////
#if !defined(SFML_STATIC)
#if defined(SFML_SYSTEM_WINDOWS)
// Windows compilers need specific (and different) keywords for export and import
#define SFML_API_EXPORT __declspec(dllexport)
#define SFML_API_IMPORT __declspec(dllimport)
// For Visual C++ compilers, we also need to turn off this annoying C4251 & C4275 warning
#ifdef _MSC_VER
#pragma warning(disable : 4251) // Using standard library types in our own exported types is okay
#pragma warning(disable : 4275) // Exporting types derived from the standard library is okay
#endif
#else // Linux, FreeBSD, macOS
#define SFML_API_EXPORT __attribute__((__visibility__("default")))
#define SFML_API_IMPORT __attribute__((__visibility__("default")))
#endif
#else
// Static build doesn't need import/export macros
#define SFML_API_EXPORT
#define SFML_API_IMPORT
#endif

View File

@ -1,70 +0,0 @@
////////////////////////////////////////////////////////////
//
// SFML - Simple and Fast Multimedia Library
// Copyright (C) 2007-2025 Laurent Gomila (laurent@sfml-dev.org)
//
// This software is provided 'as-is', without any express or implied warranty.
// In no event will the authors be held liable for any damages arising from the use of this software.
//
// Permission is granted to anyone to use this software for any purpose,
// including commercial applications, and to alter it and redistribute it freely,
// subject to the following restrictions:
//
// 1. The origin of this software must not be misrepresented;
// you must not claim that you wrote the original software.
// If you use this software in a product, an acknowledgment
// in the product documentation would be appreciated but is not required.
//
// 2. Altered source versions must be plainly marked as such,
// and must not be misrepresented as being the original software.
//
// 3. This notice may not be removed or altered from any source distribution.
//
////////////////////////////////////////////////////////////
#pragma once
////////////////////////////////////////////////////////////
/// Headers
////////////////////////////////////////////////////////////
#include <SFML/Config.hpp>
////////////////////////////////////////////////////////////
/// \file
///
/// \brief File containing SFML_DEFINE_DISCRETE_GPU_PREFERENCE
///
////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////
/// \def SFML_DEFINE_DISCRETE_GPU_PREFERENCE
///
/// \brief A macro to encourage usage of the discrete GPU
///
/// In order to inform the Nvidia/AMD driver that an SFML
/// application could benefit from using the more powerful
/// discrete GPU, special symbols have to be publicly
/// exported from the final executable.
///
/// SFML defines a helper macro to easily do this.
///
/// Place `SFML_DEFINE_DISCRETE_GPU_PREFERENCE` in the
/// global scope of a source file that will be linked into
/// the final executable. Typically it is best to place it
/// where the main function is also defined.
///
////////////////////////////////////////////////////////////
#if defined(SFML_SYSTEM_WINDOWS)
#define SFML_DEFINE_DISCRETE_GPU_PREFERENCE \
extern "C" __declspec(dllexport) unsigned long NvOptimusEnablement = 1; \
extern "C" __declspec(dllexport) unsigned long AmdPowerXpressRequestHighPerformance = 1;
#else
#define SFML_DEFINE_DISCRETE_GPU_PREFERENCE
#endif

View File

@ -1,67 +0,0 @@
////////////////////////////////////////////////////////////
//
// SFML - Simple and Fast Multimedia Library
// Copyright (C) 2007-2025 Laurent Gomila (laurent@sfml-dev.org)
//
// This software is provided 'as-is', without any express or implied warranty.
// In no event will the authors be held liable for any damages arising from the use of this software.
//
// Permission is granted to anyone to use this software for any purpose,
// including commercial applications, and to alter it and redistribute it freely,
// subject to the following restrictions:
//
// 1. The origin of this software must not be misrepresented;
// you must not claim that you wrote the original software.
// If you use this software in a product, an acknowledgment
// in the product documentation would be appreciated but is not required.
//
// 2. Altered source versions must be plainly marked as such,
// and must not be misrepresented as being the original software.
//
// 3. This notice may not be removed or altered from any source distribution.
//
////////////////////////////////////////////////////////////
#pragma once
////////////////////////////////////////////////////////////
// Headers
////////////////////////////////////////////////////////////
#include <SFML/Graphics/BlendMode.hpp>
#include <SFML/Graphics/CircleShape.hpp>
#include <SFML/Graphics/Color.hpp>
#include <SFML/Graphics/ConvexShape.hpp>
#include <SFML/Graphics/Drawable.hpp>
#include <SFML/Graphics/Font.hpp>
#include <SFML/Graphics/Glyph.hpp>
#include <SFML/Graphics/Image.hpp>
#include <SFML/Graphics/PrimitiveType.hpp>
#include <SFML/Graphics/Rect.hpp>
#include <SFML/Graphics/RectangleShape.hpp>
#include <SFML/Graphics/RenderStates.hpp>
#include <SFML/Graphics/RenderTarget.hpp>
#include <SFML/Graphics/RenderTexture.hpp>
#include <SFML/Graphics/RenderWindow.hpp>
#include <SFML/Graphics/Shader.hpp>
#include <SFML/Graphics/Shape.hpp>
#include <SFML/Graphics/Sprite.hpp>
#include <SFML/Graphics/StencilMode.hpp>
#include <SFML/Graphics/Text.hpp>
#include <SFML/Graphics/Texture.hpp>
#include <SFML/Graphics/Transform.hpp>
#include <SFML/Graphics/Transformable.hpp>
#include <SFML/Graphics/Vertex.hpp>
#include <SFML/Graphics/VertexArray.hpp>
#include <SFML/Graphics/VertexBuffer.hpp>
#include <SFML/Graphics/View.hpp>
#include <SFML/Window.hpp>
////////////////////////////////////////////////////////////
/// \defgroup graphics Graphics module
///
/// 2D graphics module: sprites, text, shapes, ...
///
////////////////////////////////////////////////////////////

View File

@ -1,220 +0,0 @@
////////////////////////////////////////////////////////////
//
// SFML - Simple and Fast Multimedia Library
// Copyright (C) 2007-2025 Laurent Gomila (laurent@sfml-dev.org)
//
// This software is provided 'as-is', without any express or implied warranty.
// In no event will the authors be held liable for any damages arising from the use of this software.
//
// Permission is granted to anyone to use this software for any purpose,
// including commercial applications, and to alter it and redistribute it freely,
// subject to the following restrictions:
//
// 1. The origin of this software must not be misrepresented;
// you must not claim that you wrote the original software.
// If you use this software in a product, an acknowledgment
// in the product documentation would be appreciated but is not required.
//
// 2. Altered source versions must be plainly marked as such,
// and must not be misrepresented as being the original software.
//
// 3. This notice may not be removed or altered from any source distribution.
//
////////////////////////////////////////////////////////////
#pragma once
////////////////////////////////////////////////////////////
// Headers
////////////////////////////////////////////////////////////
#include <SFML/Graphics/Export.hpp>
namespace sf
{
////////////////////////////////////////////////////////////
/// \brief Blending modes for drawing
///
////////////////////////////////////////////////////////////
struct SFML_GRAPHICS_API BlendMode
{
////////////////////////////////////////////////////////
/// \brief Enumeration of the blending factors
///
/// The factors are mapped directly to their OpenGL equivalents,
/// specified by glBlendFunc() or glBlendFuncSeparate().
////////////////////////////////////////////////////////
enum class Factor
{
Zero, //!< (0, 0, 0, 0)
One, //!< (1, 1, 1, 1)
SrcColor, //!< (src.r, src.g, src.b, src.a)
OneMinusSrcColor, //!< (1, 1, 1, 1) - (src.r, src.g, src.b, src.a)
DstColor, //!< (dst.r, dst.g, dst.b, dst.a)
OneMinusDstColor, //!< (1, 1, 1, 1) - (dst.r, dst.g, dst.b, dst.a)
SrcAlpha, //!< (src.a, src.a, src.a, src.a)
OneMinusSrcAlpha, //!< (1, 1, 1, 1) - (src.a, src.a, src.a, src.a)
DstAlpha, //!< (dst.a, dst.a, dst.a, dst.a)
OneMinusDstAlpha //!< (1, 1, 1, 1) - (dst.a, dst.a, dst.a, dst.a)
};
////////////////////////////////////////////////////////
/// \brief Enumeration of the blending equations
///
/// The equations are mapped directly to their OpenGL equivalents,
/// specified by glBlendEquation() or glBlendEquationSeparate().
////////////////////////////////////////////////////////
enum class Equation
{
Add, //!< Pixel = Src * SrcFactor + Dst * DstFactor
Subtract, //!< Pixel = Src * SrcFactor - Dst * DstFactor
ReverseSubtract, //!< Pixel = Dst * DstFactor - Src * SrcFactor
Min, //!< Pixel = min(Dst, Src)
Max //!< Pixel = max(Dst, Src)
};
////////////////////////////////////////////////////////////
/// \brief Default constructor
///
/// Constructs a blending mode that does alpha blending.
///
////////////////////////////////////////////////////////////
BlendMode() = default;
////////////////////////////////////////////////////////////
/// \brief Construct the blend mode given the factors and equation.
///
/// This constructor uses the same factors and equation for both
/// color and alpha components. It also defaults to the Add equation.
///
/// \param sourceFactor Specifies how to compute the source factor for the color and alpha channels.
/// \param destinationFactor Specifies how to compute the destination factor for the color and alpha channels.
/// \param blendEquation Specifies how to combine the source and destination colors and alpha.
///
////////////////////////////////////////////////////////////
BlendMode(Factor sourceFactor, Factor destinationFactor, Equation blendEquation = Equation::Add);
////////////////////////////////////////////////////////////
/// \brief Construct the blend mode given the factors and equation.
///
/// \param colorSourceFactor Specifies how to compute the source factor for the color channels.
/// \param colorDestinationFactor Specifies how to compute the destination factor for the color channels.
/// \param colorBlendEquation Specifies how to combine the source and destination colors.
/// \param alphaSourceFactor Specifies how to compute the source factor.
/// \param alphaDestinationFactor Specifies how to compute the destination factor.
/// \param alphaBlendEquation Specifies how to combine the source and destination alphas.
///
////////////////////////////////////////////////////////////
BlendMode(Factor colorSourceFactor,
Factor colorDestinationFactor,
Equation colorBlendEquation,
Factor alphaSourceFactor,
Factor alphaDestinationFactor,
Equation alphaBlendEquation);
////////////////////////////////////////////////////////////
// Member Data
////////////////////////////////////////////////////////////
Factor colorSrcFactor{BlendMode::Factor::SrcAlpha}; //!< Source blending factor for the color channels
Factor colorDstFactor{BlendMode::Factor::OneMinusSrcAlpha}; //!< Destination blending factor for the color channels
Equation colorEquation{BlendMode::Equation::Add}; //!< Blending equation for the color channels
Factor alphaSrcFactor{BlendMode::Factor::One}; //!< Source blending factor for the alpha channel
Factor alphaDstFactor{BlendMode::Factor::OneMinusSrcAlpha}; //!< Destination blending factor for the alpha channel
Equation alphaEquation{BlendMode::Equation::Add}; //!< Blending equation for the alpha channel
};
////////////////////////////////////////////////////////////
/// \relates BlendMode
/// \brief Overload of the `operator==`
///
/// \param left Left operand
/// \param right Right operand
///
/// \return `true` if blending modes are equal, `false` if they are different
///
////////////////////////////////////////////////////////////
[[nodiscard]] SFML_GRAPHICS_API bool operator==(const BlendMode& left, const BlendMode& right);
////////////////////////////////////////////////////////////
/// \relates BlendMode
/// \brief Overload of the `operator!=`
///
/// \param left Left operand
/// \param right Right operand
///
/// \return `true` if blending modes are different, `false` if they are equal
///
////////////////////////////////////////////////////////////
[[nodiscard]] SFML_GRAPHICS_API bool operator!=(const BlendMode& left, const BlendMode& right);
////////////////////////////////////////////////////////////
// Commonly used blending modes
////////////////////////////////////////////////////////////
// NOLINTBEGIN(readability-identifier-naming)
SFML_GRAPHICS_API extern const BlendMode BlendAlpha; //!< Blend source and dest according to dest alpha
SFML_GRAPHICS_API extern const BlendMode BlendAdd; //!< Add source to dest
SFML_GRAPHICS_API extern const BlendMode BlendMultiply; //!< Multiply source and dest
SFML_GRAPHICS_API extern const BlendMode BlendMin; //!< Take minimum between source and dest
SFML_GRAPHICS_API extern const BlendMode BlendMax; //!< Take maximum between source and dest
SFML_GRAPHICS_API extern const BlendMode BlendNone; //!< Overwrite dest with source
// NOLINTEND(readability-identifier-naming)
} // namespace sf
////////////////////////////////////////////////////////////
/// \class sf::BlendMode
/// \ingroup graphics
///
/// `sf::BlendMode` is a class that represents a blend mode. A blend
/// mode determines how the colors of an object you draw are
/// mixed with the colors that are already in the buffer.
///
/// The class is composed of 6 components, each of which has its
/// own public member variable:
/// \li %Color Source Factor (@ref colorSrcFactor)
/// \li %Color Destination Factor (@ref colorDstFactor)
/// \li %Color Blend Equation (@ref colorEquation)
/// \li Alpha Source Factor (@ref alphaSrcFactor)
/// \li Alpha Destination Factor (@ref alphaDstFactor)
/// \li Alpha Blend Equation (@ref alphaEquation)
///
/// The source factor specifies how the pixel you are drawing contributes
/// to the final color. The destination factor specifies how the pixel
/// already drawn in the buffer contributes to the final color.
///
/// The color channels RGB (red, green, blue; simply referred to as
/// color) and A (alpha; the transparency) can be treated separately. This
/// separation can be useful for specific blend modes, but most often you
/// won't need it and will simply treat the color as a single unit.
///
/// The blend factors and equations correspond to their OpenGL equivalents.
/// In general, the color of the resulting pixel is calculated according
/// to the following formula (`src` is the color of the source pixel, `dst`
/// the color of the destination pixel, the other variables correspond to the
/// public members, with the equations being + or - operators):
/// \code
/// dst.rgb = colorSrcFactor * src.rgb (colorEquation) colorDstFactor * dst.rgb
/// dst.a = alphaSrcFactor * src.a (alphaEquation) alphaDstFactor * dst.a
/// \endcode
/// All factors and colors are represented as floating point numbers between
/// 0 and 1. Where necessary, the result is clamped to fit in that range.
///
/// The most common blending modes are defined as constants
/// in the sf namespace:
///
/// \code
/// sf::BlendMode alphaBlending = sf::BlendAlpha;
/// sf::BlendMode additiveBlending = sf::BlendAdd;
/// sf::BlendMode multiplicativeBlending = sf::BlendMultiply;
/// sf::BlendMode noBlending = sf::BlendNone;
/// \endcode
///
/// In SFML, a blend mode can be specified every time you draw a `sf::Drawable`
/// object to a render target. It is part of the `sf::RenderStates` compound
/// that is passed to the member function `sf::RenderTarget::draw()`.
///
/// \see `sf::RenderStates`, `sf::RenderTarget`
///
////////////////////////////////////////////////////////////

View File

@ -1,165 +0,0 @@
////////////////////////////////////////////////////////////
//
// SFML - Simple and Fast Multimedia Library
// Copyright (C) 2007-2025 Laurent Gomila (laurent@sfml-dev.org)
//
// This software is provided 'as-is', without any express or implied warranty.
// In no event will the authors be held liable for any damages arising from the use of this software.
//
// Permission is granted to anyone to use this software for any purpose,
// including commercial applications, and to alter it and redistribute it freely,
// subject to the following restrictions:
//
// 1. The origin of this software must not be misrepresented;
// you must not claim that you wrote the original software.
// If you use this software in a product, an acknowledgment
// in the product documentation would be appreciated but is not required.
//
// 2. Altered source versions must be plainly marked as such,
// and must not be misrepresented as being the original software.
//
// 3. This notice may not be removed or altered from any source distribution.
//
////////////////////////////////////////////////////////////
#pragma once
////////////////////////////////////////////////////////////
// Headers
////////////////////////////////////////////////////////////
#include <SFML/Graphics/Export.hpp>
#include <SFML/Graphics/Shape.hpp>
#include <SFML/System/Vector2.hpp>
#include <cstddef>
namespace sf
{
////////////////////////////////////////////////////////////
/// \brief Specialized shape representing a circle
///
////////////////////////////////////////////////////////////
class SFML_GRAPHICS_API CircleShape : public Shape
{
public:
////////////////////////////////////////////////////////////
/// \brief Default constructor
///
/// \param radius Radius of the circle
/// \param pointCount Number of points composing the circle
///
////////////////////////////////////////////////////////////
explicit CircleShape(float radius = 0, std::size_t pointCount = 30);
////////////////////////////////////////////////////////////
/// \brief Set the radius of the circle
///
/// \param radius New radius of the circle
///
/// \see `getRadius`
///
////////////////////////////////////////////////////////////
void setRadius(float radius);
////////////////////////////////////////////////////////////
/// \brief Get the radius of the circle
///
/// \return Radius of the circle
///
/// \see `setRadius`
///
////////////////////////////////////////////////////////////
[[nodiscard]] float getRadius() const;
////////////////////////////////////////////////////////////
/// \brief Set the number of points of the circle
///
/// \param count New number of points of the circle
///
/// \see `getPointCount`
///
////////////////////////////////////////////////////////////
void setPointCount(std::size_t count);
////////////////////////////////////////////////////////////
/// \brief Get the number of points of the circle
///
/// \return Number of points of the circle
///
/// \see `setPointCount`
///
////////////////////////////////////////////////////////////
[[nodiscard]] std::size_t getPointCount() const override;
////////////////////////////////////////////////////////////
/// \brief Get a point of the circle
///
/// The returned point is in local coordinates, that is,
/// the shape's transforms (position, rotation, scale) are
/// not taken into account.
/// The result is undefined if `index` is out of the valid range.
///
/// \param index Index of the point to get, in range [0 .. getPointCount() - 1]
///
/// \return `index`-th point of the shape
///
////////////////////////////////////////////////////////////
[[nodiscard]] Vector2f getPoint(std::size_t index) const override;
////////////////////////////////////////////////////////////
/// \brief Get the geometric center of the circle
///
/// The returned point is in local coordinates, that is,
/// the shape's transforms (position, rotation, scale) are
/// not taken into account.
///
/// \return The geometric center of the shape
///
////////////////////////////////////////////////////////////
[[nodiscard]] Vector2f getGeometricCenter() const override;
private:
////////////////////////////////////////////////////////////
// Member data
////////////////////////////////////////////////////////////
float m_radius; //!< Radius of the circle
std::size_t m_pointCount; //!< Number of points composing the circle
};
} // namespace sf
////////////////////////////////////////////////////////////
/// \class sf::CircleShape
/// \ingroup graphics
///
/// This class inherits all the functions of `sf::Transformable`
/// (position, rotation, scale, bounds, ...) as well as the
/// functions of `sf::Shape` (outline, color, texture, ...).
///
/// Usage example:
/// \code
/// sf::CircleShape circle;
/// circle.setRadius(150);
/// circle.setOutlineColor(sf::Color::Red);
/// circle.setOutlineThickness(5);
/// circle.setPosition({10, 20});
/// ...
/// window.draw(circle);
/// \endcode
///
/// Since the graphics card can't draw perfect circles, we have to
/// fake them with multiple triangles connected to each other. The
/// "points count" property of `sf::CircleShape` defines how many of these
/// triangles to use, and therefore defines the quality of the circle.
///
/// The number of points can also be used for another purpose; with
/// small numbers you can create any regular polygon shape:
/// equilateral triangle, square, pentagon, hexagon, ...
///
/// \see `sf::Shape`, `sf::RectangleShape`, `sf::ConvexShape`
///
////////////////////////////////////////////////////////////

View File

@ -1,274 +0,0 @@
////////////////////////////////////////////////////////////
//
// SFML - Simple and Fast Multimedia Library
// Copyright (C) 2007-2025 Laurent Gomila (laurent@sfml-dev.org)
//
// This software is provided 'as-is', without any express or implied warranty.
// In no event will the authors be held liable for any damages arising from the use of this software.
//
// Permission is granted to anyone to use this software for any purpose,
// including commercial applications, and to alter it and redistribute it freely,
// subject to the following restrictions:
//
// 1. The origin of this software must not be misrepresented;
// you must not claim that you wrote the original software.
// If you use this software in a product, an acknowledgment
// in the product documentation would be appreciated but is not required.
//
// 2. Altered source versions must be plainly marked as such,
// and must not be misrepresented as being the original software.
//
// 3. This notice may not be removed or altered from any source distribution.
//
////////////////////////////////////////////////////////////
#pragma once
////////////////////////////////////////////////////////////
// Headers
////////////////////////////////////////////////////////////
#include <cstdint>
namespace sf
{
////////////////////////////////////////////////////////////
/// \brief Utility class for manipulating RGBA colors
///
////////////////////////////////////////////////////////////
class Color
{
public:
////////////////////////////////////////////////////////////
/// \brief Default constructor
///
/// Constructs an opaque black color. It is equivalent to
/// `sf::Color(0, 0, 0, 255)`.
///
////////////////////////////////////////////////////////////
constexpr Color() = default;
////////////////////////////////////////////////////////////
/// \brief Construct the color from its 4 RGBA components
///
/// \param red Red component (in the range [0, 255])
/// \param green Green component (in the range [0, 255])
/// \param blue Blue component (in the range [0, 255])
/// \param alpha Alpha (opacity) component (in the range [0, 255])
///
////////////////////////////////////////////////////////////
constexpr Color(std::uint8_t red, std::uint8_t green, std::uint8_t blue, std::uint8_t alpha = 255);
////////////////////////////////////////////////////////////
/// \brief Construct the color from 32-bit unsigned integer
///
/// \param color Number containing the RGBA components (in that order)
///
////////////////////////////////////////////////////////////
constexpr explicit Color(std::uint32_t color);
////////////////////////////////////////////////////////////
/// \brief Retrieve the color as a 32-bit unsigned integer
///
/// \return Color represented as a 32-bit unsigned integer
///
////////////////////////////////////////////////////////////
[[nodiscard]] constexpr std::uint32_t toInteger() const;
////////////////////////////////////////////////////////////
// Static member data
////////////////////////////////////////////////////////////
// NOLINTBEGIN(readability-identifier-naming)
static const Color Black; //!< Black predefined color
static const Color White; //!< White predefined color
static const Color Red; //!< Red predefined color
static const Color Green; //!< Green predefined color
static const Color Blue; //!< Blue predefined color
static const Color Yellow; //!< Yellow predefined color
static const Color Magenta; //!< Magenta predefined color
static const Color Cyan; //!< Cyan predefined color
static const Color Transparent; //!< Transparent (black) predefined color
// NOLINTEND(readability-identifier-naming)
////////////////////////////////////////////////////////////
// Member data
////////////////////////////////////////////////////////////
std::uint8_t r{}; //!< Red component
std::uint8_t g{}; //!< Green component
std::uint8_t b{}; //!< Blue component
std::uint8_t a{255}; //!< Alpha (opacity) component
};
////////////////////////////////////////////////////////////
/// \relates Color
/// \brief Overload of the `operator==`
///
/// This operator compares two colors and check if they are equal.
///
/// \param left Left operand
/// \param right Right operand
///
/// \return `true` if colors are equal, `false` if they are different
///
////////////////////////////////////////////////////////////
[[nodiscard]] constexpr bool operator==(Color left, Color right);
////////////////////////////////////////////////////////////
/// \relates Color
/// \brief Overload of the `operator!=`
///
/// This operator compares two colors and check if they are different.
///
/// \param left Left operand
/// \param right Right operand
///
/// \return `true` if colors are different, `false` if they are equal
///
////////////////////////////////////////////////////////////
[[nodiscard]] constexpr bool operator!=(Color left, Color right);
////////////////////////////////////////////////////////////
/// \relates Color
/// \brief Overload of the binary `operator+`
///
/// This operator returns the component-wise sum of two colors.
/// Components that exceed 255 are clamped to 255.
///
/// \param left Left operand
/// \param right Right operand
///
/// \return Result of \a left + \a right
///
////////////////////////////////////////////////////////////
[[nodiscard]] constexpr Color operator+(Color left, Color right);
////////////////////////////////////////////////////////////
/// \relates Color
/// \brief Overload of the binary `operator-`
///
/// This operator returns the component-wise subtraction of two colors.
/// Components below 0 are clamped to 0.
///
/// \param left Left operand
/// \param right Right operand
///
/// \return Result of \a left - \a right
///
////////////////////////////////////////////////////////////
[[nodiscard]] constexpr Color operator-(Color left, Color right);
////////////////////////////////////////////////////////////
/// \relates Color
/// \brief Overload of the binary `operator*`
///
/// This operator returns the component-wise multiplication
/// (also called "modulation") of two colors.
/// Components are then divided by 255 so that the result is
/// still in the range [0, 255].
///
/// \param left Left operand
/// \param right Right operand
///
/// \return Result of \a left * \a right
///
////////////////////////////////////////////////////////////
[[nodiscard]] constexpr Color operator*(Color left, Color right);
////////////////////////////////////////////////////////////
/// \relates Color
/// \brief Overload of the binary `operator+=`
///
/// This operator computes the component-wise sum of two colors,
/// and assigns the result to the left operand.
/// Components that exceed 255 are clamped to 255.
///
/// \param left Left operand
/// \param right Right operand
///
/// \return Reference to \a left
///
////////////////////////////////////////////////////////////
constexpr Color& operator+=(Color& left, Color right);
////////////////////////////////////////////////////////////
/// \relates Color
/// \brief Overload of the binary `operator-=`
///
/// This operator computes the component-wise subtraction of two colors,
/// and assigns the result to the left operand.
/// Components below 0 are clamped to 0.
///
/// \param left Left operand
/// \param right Right operand
///
/// \return Reference to \a left
///
////////////////////////////////////////////////////////////
constexpr Color& operator-=(Color& left, Color right);
////////////////////////////////////////////////////////////
/// \relates Color
/// \brief Overload of the binary `operator*=`
///
/// This operator returns the component-wise multiplication
/// (also called "modulation") of two colors, and assigns
/// the result to the left operand.
/// Components are then divided by 255 so that the result is
/// still in the range [0, 255].
///
/// \param left Left operand
/// \param right Right operand
///
/// \return Reference to \a left
///
////////////////////////////////////////////////////////////
constexpr Color& operator*=(Color& left, Color right);
} // namespace sf
#include <SFML/Graphics/Color.inl>
////////////////////////////////////////////////////////////
/// \class sf::Color
/// \ingroup graphics
///
/// `sf::Color` is a simple color class composed of 4 components:
/// \li Red
/// \li Green
/// \li Blue
/// \li Alpha (opacity)
///
/// Each component is a public member, an unsigned integer in
/// the range [0, 255]. Thus, colors can be constructed and
/// manipulated very easily:
///
/// \code
/// sf::Color color(255, 0, 0); // red
/// color.r = 0; // make it black
/// color.b = 128; // make it dark blue
/// \endcode
///
/// The fourth component of colors, named "alpha", represents
/// the opacity of the color. A color with an alpha value of
/// 255 will be fully opaque, while an alpha value of 0 will
/// make a color fully transparent, whatever the value of the
/// other components is.
///
/// The most common colors are already defined as static variables:
/// \code
/// sf::Color black = sf::Color::Black;
/// sf::Color white = sf::Color::White;
/// sf::Color red = sf::Color::Red;
/// sf::Color green = sf::Color::Green;
/// sf::Color blue = sf::Color::Blue;
/// sf::Color yellow = sf::Color::Yellow;
/// sf::Color magenta = sf::Color::Magenta;
/// sf::Color cyan = sf::Color::Cyan;
/// sf::Color transparent = sf::Color::Transparent;
/// \endcode
///
/// Colors can also be added and modulated (multiplied) using the
/// overloaded operators + and *.
///
////////////////////////////////////////////////////////////

View File

@ -1,156 +0,0 @@
////////////////////////////////////////////////////////////
//
// SFML - Simple and Fast Multimedia Library
// Copyright (C) 2007-2025 Laurent Gomila (laurent@sfml-dev.org)
//
// This software is provided 'as-is', without any express or implied warranty.
// In no event will the authors be held liable for any damages arising from the use of this software.
//
// Permission is granted to anyone to use this software for any purpose,
// including commercial applications, and to alter it and redistribute it freely,
// subject to the following restrictions:
//
// 1. The origin of this software must not be misrepresented;
// you must not claim that you wrote the original software.
// If you use this software in a product, an acknowledgment
// in the product documentation would be appreciated but is not required.
//
// 2. Altered source versions must be plainly marked as such,
// and must not be misrepresented as being the original software.
//
// 3. This notice may not be removed or altered from any source distribution.
//
////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////
// Headers
////////////////////////////////////////////////////////////
#include <SFML/Graphics/Color.hpp> // NOLINT(misc-header-include-cycle)
namespace sf
{
////////////////////////////////////////////////////////////
constexpr Color::Color(std::uint8_t red, std::uint8_t green, std::uint8_t blue, std::uint8_t alpha) :
r(red),
g(green),
b(blue),
a(alpha)
{
}
////////////////////////////////////////////////////////////
constexpr Color::Color(std::uint32_t color) :
r(static_cast<std::uint8_t>((color & 0xff000000) >> 24)),
g(static_cast<std::uint8_t>((color & 0x00ff0000) >> 16)),
b(static_cast<std::uint8_t>((color & 0x0000ff00) >> 8)),
a(static_cast<std::uint8_t>(color & 0x000000ff))
{
}
////////////////////////////////////////////////////////////
constexpr std::uint32_t Color::toInteger() const
{
return static_cast<std::uint32_t>((r << 24) | (g << 16) | (b << 8) | a);
}
////////////////////////////////////////////////////////////
constexpr bool operator==(Color left, Color right)
{
return (left.r == right.r) && (left.g == right.g) && (left.b == right.b) && (left.a == right.a);
}
////////////////////////////////////////////////////////////
constexpr bool operator!=(Color left, Color right)
{
return !(left == right);
}
////////////////////////////////////////////////////////////
constexpr Color operator+(Color left, Color right)
{
const auto clampedAdd = [](std::uint8_t lhs, std::uint8_t rhs)
{
const int intResult = int{lhs} + int{rhs};
return static_cast<std::uint8_t>(intResult < 255 ? intResult : 255);
};
return {clampedAdd(left.r, right.r),
clampedAdd(left.g, right.g),
clampedAdd(left.b, right.b),
clampedAdd(left.a, right.a)};
}
////////////////////////////////////////////////////////////
constexpr Color operator-(Color left, Color right)
{
const auto clampedSub = [](std::uint8_t lhs, std::uint8_t rhs)
{
const int intResult = int{lhs} - int{rhs};
return static_cast<std::uint8_t>(intResult > 0 ? intResult : 0);
};
return {clampedSub(left.r, right.r),
clampedSub(left.g, right.g),
clampedSub(left.b, right.b),
clampedSub(left.a, right.a)};
}
////////////////////////////////////////////////////////////
constexpr Color operator*(Color left, Color right)
{
const auto scaledMul = [](std::uint8_t lhs, std::uint8_t rhs)
{
const auto uint16Result = static_cast<std::uint16_t>(std::uint16_t{lhs} * std::uint16_t{rhs});
return static_cast<std::uint8_t>(uint16Result / 255u);
};
return {scaledMul(left.r, right.r), scaledMul(left.g, right.g), scaledMul(left.b, right.b), scaledMul(left.a, right.a)};
}
////////////////////////////////////////////////////////////
constexpr Color& operator+=(Color& left, Color right)
{
return left = left + right;
}
////////////////////////////////////////////////////////////
constexpr Color& operator-=(Color& left, Color right)
{
return left = left - right;
}
////////////////////////////////////////////////////////////
constexpr Color& operator*=(Color& left, Color right)
{
return left = left * right;
}
////////////////////////////////////////////////////////////
// Static member data
////////////////////////////////////////////////////////////
// Note: the 'inline' keyword here is technically not required, but VS2019 fails
// to compile with a bogus "multiple definition" error if not explicitly used.
inline constexpr Color Color::Black(0, 0, 0);
inline constexpr Color Color::White(255, 255, 255);
inline constexpr Color Color::Red(255, 0, 0);
inline constexpr Color Color::Green(0, 255, 0);
inline constexpr Color Color::Blue(0, 0, 255);
inline constexpr Color Color::Yellow(255, 255, 0);
inline constexpr Color Color::Magenta(255, 0, 255);
inline constexpr Color Color::Cyan(0, 255, 255);
inline constexpr Color Color::Transparent(0, 0, 0, 0);
} // namespace sf

View File

@ -1,155 +0,0 @@
////////////////////////////////////////////////////////////
//
// SFML - Simple and Fast Multimedia Library
// Copyright (C) 2007-2025 Laurent Gomila (laurent@sfml-dev.org)
//
// This software is provided 'as-is', without any express or implied warranty.
// In no event will the authors be held liable for any damages arising from the use of this software.
//
// Permission is granted to anyone to use this software for any purpose,
// including commercial applications, and to alter it and redistribute it freely,
// subject to the following restrictions:
//
// 1. The origin of this software must not be misrepresented;
// you must not claim that you wrote the original software.
// If you use this software in a product, an acknowledgment
// in the product documentation would be appreciated but is not required.
//
// 2. Altered source versions must be plainly marked as such,
// and must not be misrepresented as being the original software.
//
// 3. This notice may not be removed or altered from any source distribution.
//
////////////////////////////////////////////////////////////
#pragma once
////////////////////////////////////////////////////////////
// Headers
////////////////////////////////////////////////////////////
#include <SFML/Graphics/Export.hpp>
#include <SFML/Graphics/Shape.hpp>
#include <vector>
#include <cstddef>
namespace sf
{
////////////////////////////////////////////////////////////
/// \brief Specialized shape representing a convex polygon
///
////////////////////////////////////////////////////////////
class SFML_GRAPHICS_API ConvexShape : public Shape
{
public:
////////////////////////////////////////////////////////////
/// \brief Default constructor
///
/// \param pointCount Number of points of the polygon
///
////////////////////////////////////////////////////////////
explicit ConvexShape(std::size_t pointCount = 0);
////////////////////////////////////////////////////////////
/// \brief Set the number of points of the polygon
///
/// For the shape to be rendered as expected, `count` must
/// be greater or equal to 3.
///
/// \param count New number of points of the polygon
///
/// \see `getPointCount`
///
////////////////////////////////////////////////////////////
void setPointCount(std::size_t count);
////////////////////////////////////////////////////////////
/// \brief Get the number of points of the polygon
///
/// \return Number of points of the polygon
///
/// \see `setPointCount`
///
////////////////////////////////////////////////////////////
[[nodiscard]] std::size_t getPointCount() const override;
////////////////////////////////////////////////////////////
/// \brief Set the position of a point
///
/// Don't forget that the shape must be convex and the
/// order of points matters. Points should not overlap.
/// This applies to rendering; it is explicitly allowed
/// to temporarily have non-convex or degenerate shapes
/// when not drawn (e.g. during shape initialization).
///
/// Point count must be specified beforehand. The behavior is
/// undefined if `index` is greater than or equal to getPointCount.
///
/// \param index Index of the point to change, in range [0 .. getPointCount() - 1]
/// \param point New position of the point
///
/// \see `getPoint`
///
////////////////////////////////////////////////////////////
void setPoint(std::size_t index, Vector2f point);
////////////////////////////////////////////////////////////
/// \brief Get the position of a point
///
/// The returned point is in local coordinates, that is,
/// the shape's transforms (position, rotation, scale) are
/// not taken into account.
/// The result is undefined if `index` is out of the valid range.
///
/// \param index Index of the point to get, in range [0 .. getPointCount() - 1]
///
/// \return Position of the `index`-th point of the polygon
///
/// \see `setPoint`
///
////////////////////////////////////////////////////////////
[[nodiscard]] Vector2f getPoint(std::size_t index) const override;
private:
////////////////////////////////////////////////////////////
// Member data
////////////////////////////////////////////////////////////
std::vector<Vector2f> m_points; //!< Points composing the convex polygon
};
} // namespace sf
////////////////////////////////////////////////////////////
/// \class sf::ConvexShape
/// \ingroup graphics
///
/// This class inherits all the functions of `sf::Transformable`
/// (position, rotation, scale, bounds, ...) as well as the
/// functions of `sf::Shape` (outline, color, texture, ...).
///
/// It is important to keep in mind that a convex shape must
/// always be... convex, otherwise it may not be drawn correctly.
/// Moreover, the points must be defined in order; using a random
/// order would result in an incorrect shape.
///
/// Usage example:
/// \code
/// sf::ConvexShape polygon;
/// polygon.setPointCount(3);
/// polygon.setPoint(0, sf::Vector2f(0, 0));
/// polygon.setPoint(1, sf::Vector2f(0, 10));
/// polygon.setPoint(2, sf::Vector2f(25, 5));
/// polygon.setOutlineColor(sf::Color::Red);
/// polygon.setOutlineThickness(5);
/// polygon.setPosition({10, 20});
/// ...
/// window.draw(polygon);
/// \endcode
///
/// \see `sf::Shape`, `sf::RectangleShape`, `sf::CircleShape`
///
////////////////////////////////////////////////////////////

View File

@ -1,43 +0,0 @@
////////////////////////////////////////////////////////////
//
// SFML - Simple and Fast Multimedia Library
// Copyright (C) 2007-2025 Laurent Gomila (laurent@sfml-dev.org)
//
// This software is provided 'as-is', without any express or implied warranty.
// In no event will the authors be held liable for any damages arising from the use of this software.
//
// Permission is granted to anyone to use this software for any purpose,
// including commercial applications, and to alter it and redistribute it freely,
// subject to the following restrictions:
//
// 1. The origin of this software must not be misrepresented;
// you must not claim that you wrote the original software.
// If you use this software in a product, an acknowledgment
// in the product documentation would be appreciated but is not required.
//
// 2. Altered source versions must be plainly marked as such,
// and must not be misrepresented as being the original software.
//
// 3. This notice may not be removed or altered from any source distribution.
//
////////////////////////////////////////////////////////////
#pragma once
namespace sf
{
////////////////////////////////////////////////////////////
/// \ingroup graphics
/// \brief Types of texture coordinates that can be used for rendering
///
/// \see `sf::Texture::bind`
///
////////////////////////////////////////////////////////////
enum class CoordinateType
{
Normalized, //!< Texture coordinates in range [0 .. 1]
Pixels //!< Texture coordinates in range [0 .. size]
};
} // namespace sf

View File

@ -1,120 +0,0 @@
////////////////////////////////////////////////////////////
//
// SFML - Simple and Fast Multimedia Library
// Copyright (C) 2007-2025 Laurent Gomila (laurent@sfml-dev.org)
//
// This software is provided 'as-is', without any express or implied warranty.
// In no event will the authors be held liable for any damages arising from the use of this software.
//
// Permission is granted to anyone to use this software for any purpose,
// including commercial applications, and to alter it and redistribute it freely,
// subject to the following restrictions:
//
// 1. The origin of this software must not be misrepresented;
// you must not claim that you wrote the original software.
// If you use this software in a product, an acknowledgment
// in the product documentation would be appreciated but is not required.
//
// 2. Altered source versions must be plainly marked as such,
// and must not be misrepresented as being the original software.
//
// 3. This notice may not be removed or altered from any source distribution.
//
////////////////////////////////////////////////////////////
#pragma once
////////////////////////////////////////////////////////////
// Headers
////////////////////////////////////////////////////////////
#include <SFML/Graphics/Export.hpp>
namespace sf
{
class RenderTarget;
struct RenderStates;
////////////////////////////////////////////////////////////
/// \brief Abstract base class for objects that can be drawn
/// to a render target
///
////////////////////////////////////////////////////////////
class SFML_GRAPHICS_API Drawable
{
public:
////////////////////////////////////////////////////////////
/// \brief Virtual destructor
///
////////////////////////////////////////////////////////////
virtual ~Drawable() = default;
protected:
friend class RenderTarget;
////////////////////////////////////////////////////////////
/// \brief Draw the object to a render target
///
/// This is a pure virtual function that has to be implemented
/// by the derived class to define how the drawable should be
/// drawn.
///
/// \param target Render target to draw to
/// \param states Current render states
///
////////////////////////////////////////////////////////////
virtual void draw(RenderTarget& target, RenderStates states) const = 0;
};
} // namespace sf
////////////////////////////////////////////////////////////
/// \class sf::Drawable
/// \ingroup graphics
///
/// `sf::Drawable` is a very simple base class that allows objects
/// of derived classes to be drawn to a `sf::RenderTarget`.
///
/// All you have to do in your derived class is to override the
/// draw virtual function.
///
/// Note that inheriting from `sf::Drawable` is not mandatory,
/// but it allows this nice syntax `window.draw(object)` rather
/// than `object.draw(window)`, which is more consistent with other
/// SFML classes.
///
/// Example:
/// \code
/// class MyDrawable : public sf::Drawable
/// {
/// public:
///
/// ...
///
/// private:
///
/// void draw(sf::RenderTarget& target, sf::RenderStates states) const override
/// {
/// // You can draw other high-level objects
/// target.draw(m_sprite, states);
///
/// // ... or use the low-level API
/// states.texture = &m_texture;
/// target.draw(m_vertices, states);
///
/// // ... or draw with OpenGL directly
/// glBegin(GL_TRIANGLES);
/// ...
/// glEnd();
/// }
///
/// sf::Sprite m_sprite;
/// sf::Texture m_texture;
/// sf::VertexArray m_vertices;
/// };
/// \endcode
///
/// \see `sf::RenderTarget`
///
////////////////////////////////////////////////////////////

View File

@ -1,44 +0,0 @@
////////////////////////////////////////////////////////////
//
// SFML - Simple and Fast Multimedia Library
// Copyright (C) 2007-2025 Laurent Gomila (laurent@sfml-dev.org)
//
// This software is provided 'as-is', without any express or implied warranty.
// In no event will the authors be held liable for any damages arising from the use of this software.
//
// Permission is granted to anyone to use this software for any purpose,
// including commercial applications, and to alter it and redistribute it freely,
// subject to the following restrictions:
//
// 1. The origin of this software must not be misrepresented;
// you must not claim that you wrote the original software.
// If you use this software in a product, an acknowledgment
// in the product documentation would be appreciated but is not required.
//
// 2. Altered source versions must be plainly marked as such,
// and must not be misrepresented as being the original software.
//
// 3. This notice may not be removed or altered from any source distribution.
//
////////////////////////////////////////////////////////////
#pragma once
////////////////////////////////////////////////////////////
// Headers
////////////////////////////////////////////////////////////
#include <SFML/Config.hpp>
////////////////////////////////////////////////////////////
// Portable import / export macros
////////////////////////////////////////////////////////////
#if defined(SFML_GRAPHICS_EXPORTS)
#define SFML_GRAPHICS_API SFML_API_EXPORT
#else
#define SFML_GRAPHICS_API SFML_API_IMPORT
#endif

View File

@ -1,529 +0,0 @@
////////////////////////////////////////////////////////////
//
// SFML - Simple and Fast Multimedia Library
// Copyright (C) 2007-2025 Laurent Gomila (laurent@sfml-dev.org)
//
// This software is provided 'as-is', without any express or implied warranty.
// In no event will the authors be held liable for any damages arising from the use of this software.
//
// Permission is granted to anyone to use this software for any purpose,
// including commercial applications, and to alter it and redistribute it freely,
// subject to the following restrictions:
//
// 1. The origin of this software must not be misrepresented;
// you must not claim that you wrote the original software.
// If you use this software in a product, an acknowledgment
// in the product documentation would be appreciated but is not required.
//
// 2. Altered source versions must be plainly marked as such,
// and must not be misrepresented as being the original software.
//
// 3. This notice may not be removed or altered from any source distribution.
//
////////////////////////////////////////////////////////////
#pragma once
////////////////////////////////////////////////////////////
// Headers
////////////////////////////////////////////////////////////
#include <SFML/Graphics/Export.hpp>
#include <SFML/Graphics/Glyph.hpp>
#include <SFML/Graphics/Rect.hpp>
#include <SFML/Graphics/Texture.hpp>
#include <SFML/System/Vector2.hpp>
#include <filesystem>
#include <memory>
#include <string>
#include <string_view>
#include <unordered_map>
#include <vector>
#include <cstddef>
#include <cstdint>
namespace sf
{
class InputStream;
////////////////////////////////////////////////////////////
/// \brief Class for loading and manipulating character fonts
///
////////////////////////////////////////////////////////////
class SFML_GRAPHICS_API Font
{
public:
////////////////////////////////////////////////////////////
/// \brief Holds various information about a font
///
////////////////////////////////////////////////////////////
struct Info
{
std::string family; //!< The font family
};
////////////////////////////////////////////////////////////
/// \brief Default constructor
///
/// Construct an empty font that does not contain any glyphs.
///
////////////////////////////////////////////////////////////
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 sf::Exception if opening was unsuccessful
///
/// \see `openFromFile`, `openFromMemory`, `openFromStream`
///
////////////////////////////////////////////////////////////
explicit 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 `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 sf::Exception 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 `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 sf::Exception if loading was unsuccessful
///
/// \see `openFromFile`, `openFromMemory`, `openFromStream`
///
////////////////////////////////////////////////////////////
explicit Font(InputStream& stream);
////////////////////////////////////////////////////////////
/// \brief Open the font from a file
///
/// The supported font formats are: TrueType, Type 1, CFF,
/// OpenType, SFNT, X11 PCF, Windows FNT, BDF, PFR and Type 42.
/// 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 load
///
/// \return `true` if opening succeeded, `false` if it failed
///
/// \see `openFromMemory`, `openFromStream`
///
////////////////////////////////////////////////////////////
[[nodiscard]] bool openFromFile(const std::filesystem::path& filename);
////////////////////////////////////////////////////////////
/// \brief Open the font from a file in memory
///
/// The supported font formats are: TrueType, Type 1, CFF,
/// OpenType, SFNT, X11 PCF, Windows FNT, BDF, PFR and Type 42.
///
/// \warning SFML cannot preload all the font data in this
/// function, so the buffer pointed by `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
///
/// \return `true` if opening succeeded, `false` if it failed
///
/// \see `openFromFile`, `openFromStream`
///
////////////////////////////////////////////////////////////
[[nodiscard]] bool openFromMemory(const void* data, std::size_t sizeInBytes);
////////////////////////////////////////////////////////////
/// \brief Open the font from a custom stream
///
/// The supported font formats are: TrueType, Type 1, CFF,
/// OpenType, SFNT, X11 PCF, Windows FNT, BDF, PFR and Type 42.
///
/// \warning SFML cannot preload all the font data in this
/// function, so the stream has to remain accessible until
/// the `sf::Font` object opens a new font or is destroyed.
///
/// \param stream Source stream to read from
///
/// \return `true` if opening succeeded, `false` if it failed
///
/// \see `openFromFile`, `openFromMemory`
///
////////////////////////////////////////////////////////////
[[nodiscard]] bool openFromStream(InputStream& stream);
////////////////////////////////////////////////////////////
/// \brief Get the font information
///
/// \return A structure that holds the font information
///
////////////////////////////////////////////////////////////
[[nodiscard]] const Info& getInfo() const;
////////////////////////////////////////////////////////////
/// \brief Retrieve a glyph of the font
///
/// If the font is a bitmap font, not all character sizes
/// might be available. If the glyph is not available at the
/// requested size, an empty glyph is returned.
///
/// You may want to use `hasGlyph` to determine if the
/// glyph exists before requesting it. If the glyph does not
/// exist, a font specific default is returned.
///
/// Be aware that using a negative value for the outline
/// thickness will cause distorted rendering.
///
/// \param codePoint Unicode code point of the character to get
/// \param characterSize Reference character size
/// \param bold Retrieve the bold version or the regular one?
/// \param outlineThickness Thickness of outline (when != 0 the glyph will not be filled)
///
/// \return The glyph corresponding to `codePoint` and `characterSize`
///
////////////////////////////////////////////////////////////
[[nodiscard]] const Glyph& getGlyph(char32_t codePoint, unsigned int characterSize, bool bold, float outlineThickness = 0) const;
////////////////////////////////////////////////////////////
/// \brief Determine if this font has a glyph representing the requested code point
///
/// Most fonts only include a very limited selection of glyphs from
/// specific Unicode subsets, like Latin, Cyrillic, or Asian characters.
///
/// While code points without representation will return a font specific
/// default character, it might be useful to verify whether specific
/// code points are included to determine whether a font is suited
/// to display text in a specific language.
///
/// \param codePoint Unicode code point to check
///
/// \return `true` if the codepoint has a glyph representation, `false` otherwise
///
////////////////////////////////////////////////////////////
[[nodiscard]] bool hasGlyph(char32_t codePoint) const;
////////////////////////////////////////////////////////////
/// \brief Get the kerning offset of two glyphs
///
/// The kerning is an extra offset (negative) to apply between two
/// glyphs when rendering them, to make the pair look more "natural".
/// For example, the pair "AV" have a special kerning to make them
/// closer than other characters. Most of the glyphs pairs have a
/// kerning offset of zero, though.
///
/// \param first Unicode code point of the first character
/// \param second Unicode code point of the second character
/// \param characterSize Reference character size
/// \param bold Retrieve the bold version or the regular one?
///
/// \return Kerning value for `first` and `second`, in pixels
///
////////////////////////////////////////////////////////////
[[nodiscard]] float getKerning(std::uint32_t first, std::uint32_t second, unsigned int characterSize, bool bold = false) const;
////////////////////////////////////////////////////////////
/// \brief Get the line spacing
///
/// Line spacing is the vertical offset to apply between two
/// consecutive lines of text.
///
/// \param characterSize Reference character size
///
/// \return Line spacing, in pixels
///
////////////////////////////////////////////////////////////
[[nodiscard]] float getLineSpacing(unsigned int characterSize) const;
////////////////////////////////////////////////////////////
/// \brief Get the position of the underline
///
/// Underline position is the vertical offset to apply between the
/// baseline and the underline.
///
/// \param characterSize Reference character size
///
/// \return Underline position, in pixels
///
/// \see `getUnderlineThickness`
///
////////////////////////////////////////////////////////////
[[nodiscard]] float getUnderlinePosition(unsigned int characterSize) const;
////////////////////////////////////////////////////////////
/// \brief Get the thickness of the underline
///
/// Underline thickness is the vertical size of the underline.
///
/// \param characterSize Reference character size
///
/// \return Underline thickness, in pixels
///
/// \see `getUnderlinePosition`
///
////////////////////////////////////////////////////////////
[[nodiscard]] float getUnderlineThickness(unsigned int characterSize) const;
////////////////////////////////////////////////////////////
/// \brief Retrieve the texture containing the loaded glyphs of a certain size
///
/// The contents of the returned texture changes as more glyphs
/// are requested, thus it is not very relevant. It is mainly
/// used internally by `sf::Text`.
///
/// \param characterSize Reference character size
///
/// \return Texture containing the glyphs of the requested size
///
////////////////////////////////////////////////////////////
[[nodiscard]] const Texture& getTexture(unsigned int characterSize) const;
////////////////////////////////////////////////////////////
/// \brief Enable or disable the smooth filter
///
/// When the filter is activated, the font appears smoother
/// so that pixels are less noticeable. However if you want
/// the font to look exactly the same as its source file,
/// you should disable it.
/// The smooth filter is enabled by default.
///
/// \param smooth `true` to enable smoothing, `false` to disable it
///
/// \see `isSmooth`
///
////////////////////////////////////////////////////////////
void setSmooth(bool smooth);
////////////////////////////////////////////////////////////
/// \brief Tell whether the smooth filter is enabled or not
///
/// \return `true` if smoothing is enabled, `false` if it is disabled
///
/// \see `setSmooth`
///
////////////////////////////////////////////////////////////
[[nodiscard]] bool isSmooth() const;
private:
////////////////////////////////////////////////////////////
/// \brief Structure defining a row of glyphs
///
////////////////////////////////////////////////////////////
struct Row
{
Row(unsigned int rowTop, unsigned int rowHeight) : top(rowTop), height(rowHeight)
{
}
unsigned int width{}; //!< Current width of the row
unsigned int top; //!< Y position of the row into the texture
unsigned int height; //!< Height of the row
};
////////////////////////////////////////////////////////////
// Types
////////////////////////////////////////////////////////////
using GlyphTable = std::unordered_map<std::uint64_t, Glyph>; //!< Table mapping a codepoint to its glyph
////////////////////////////////////////////////////////////
/// \brief Structure defining a page of glyphs
///
////////////////////////////////////////////////////////////
struct Page
{
explicit Page(bool smooth);
GlyphTable glyphs; //!< Table mapping code points to their corresponding glyph
Texture texture; //!< Texture containing the pixels of the glyphs
unsigned int nextRow{3}; //!< Y position of the next new row in the texture
std::vector<Row> rows; //!< List containing the position of all the existing rows
};
////////////////////////////////////////////////////////////
/// \brief Free all the internal resources
///
////////////////////////////////////////////////////////////
void cleanup();
////////////////////////////////////////////////////////////
/// \brief Open from stream and print errors with custom message
///
////////////////////////////////////////////////////////////
[[nodiscard]] bool openFromStreamImpl(InputStream& stream, std::string_view type);
////////////////////////////////////////////////////////////
/// \brief Find or create the glyphs page corresponding to the given character size
///
/// \param characterSize Reference character size
///
/// \return The glyphs page corresponding to \a characterSize
///
////////////////////////////////////////////////////////////
Page& loadPage(unsigned int characterSize) const;
////////////////////////////////////////////////////////////
/// \brief Load a new glyph and store it in the cache
///
/// \param codePoint Unicode code point of the character to load
/// \param characterSize Reference character size
/// \param bold Retrieve the bold version or the regular one?
/// \param outlineThickness Thickness of outline (when != 0 the glyph will not be filled)
///
/// \return The glyph corresponding to `codePoint` and `characterSize`
///
////////////////////////////////////////////////////////////
Glyph loadGlyph(char32_t codePoint, unsigned int characterSize, bool bold, float outlineThickness) const;
////////////////////////////////////////////////////////////
/// \brief Find a suitable rectangle within the texture for a glyph
///
/// \param page Page of glyphs to search in
/// \param size Width and height of the rectangle
///
/// \return Found rectangle within the texture
///
////////////////////////////////////////////////////////////
IntRect findGlyphRect(Page& page, Vector2u size) const;
////////////////////////////////////////////////////////////
/// \brief Make sure that the given size is the current one
///
/// \param characterSize Reference character size
///
/// \return `true` on success, `false` if any error happened
///
////////////////////////////////////////////////////////////
[[nodiscard]] bool setCurrentSize(unsigned int characterSize) const;
////////////////////////////////////////////////////////////
// Types
////////////////////////////////////////////////////////////
struct FontHandles;
using PageTable = std::unordered_map<unsigned int, Page>; //!< Table mapping a character size to its page (texture)
////////////////////////////////////////////////////////////
// Member data
////////////////////////////////////////////////////////////
std::shared_ptr<FontHandles> m_fontHandles; //!< Shared information about the internal font instance
bool m_isSmooth{true}; //!< Status of the smooth filter
Info m_info; //!< Information about the font
mutable PageTable m_pages; //!< Table containing the glyphs pages by character size
mutable std::vector<std::uint8_t> m_pixelBuffer; //!< Pixel buffer holding a glyph's pixels before being written to the texture
std::shared_ptr<InputStream> m_stream; //!< Stream for openFromFile and openFromMemory
};
} // namespace sf
////////////////////////////////////////////////////////////
/// \class sf::Font
/// \ingroup graphics
///
/// Fonts can be opened from a file, from memory or from a custom
/// stream, and supports the most common types of fonts. See
/// 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:
/// \li Global metrics, such as the line spacing
/// \li Per-glyph metrics, such as bounding box or kerning
/// \li Pixel representation of glyphs
///
/// Fonts alone are not very useful: they hold the font data
/// but cannot make anything useful of it. To do so you need to
/// use the `sf::Text` class, which is able to properly output text
/// with several options such as character size, style, color,
/// position, rotation, etc.
/// This separation allows more flexibility and better performances:
/// indeed a `sf::Font` is a heavy resource, and any operation on it
/// is slow (often too slow for real-time applications). On the other
/// side, a `sf::Text` is a lightweight object which can combine the
/// glyphs data and metrics of a `sf::Font` to display any text on a
/// render target.
/// Note that it is also possible to bind several `sf::Text` instances
/// to the same `sf::Font`.
///
/// It is important to note that the `sf::Text` instance doesn't
/// copy the font that it uses, it only keeps a reference to it.
/// Thus, a `sf::Font` must not be destructed while it is
/// used by a `sf::Text` (i.e. never write a function that
/// uses a local `sf::Font` instance for creating a text).
///
/// Usage example:
/// \code
/// // Open a new font
/// const sf::Font font("arial.ttf");
///
/// // Create a text which uses our font
/// sf::Text text1(font);
/// text1.setCharacterSize(30);
/// text1.setStyle(sf::Text::Regular);
///
/// // Create another text using the same font, but with different parameters
/// sf::Text text2(font);
/// text2.setCharacterSize(50);
/// text2.setStyle(sf::Text::Italic);
/// \endcode
///
/// Apart from opening font files, and passing them to instances
/// of `sf::Text`, you should normally not have to deal directly
/// with this class. However, it may be useful to access the
/// font metrics or rasterized glyphs for advanced usage.
///
/// Note that if the font is a bitmap font, it is not scalable,
/// thus not all requested sizes will be available to use. This
/// needs to be taken into consideration when using `sf::Text`.
/// If you need to display text of a certain size, make sure the
/// corresponding bitmap font that supports that size is used.
///
/// \see `sf::Text`
///
////////////////////////////////////////////////////////////

View File

@ -1,224 +0,0 @@
////////////////////////////////////////////////////////////
//
// SFML - Simple and Fast Multimedia Library
// Copyright (C) 2007-2025 Laurent Gomila (laurent@sfml-dev.org)
//
// This software is provided 'as-is', without any express or implied warranty.
// In no event will the authors be held liable for any damages arising from the use of this software.
//
// Permission is granted to anyone to use this software for any purpose,
// including commercial applications, and to alter it and redistribute it freely,
// subject to the following restrictions:
//
// 1. The origin of this software must not be misrepresented;
// you must not claim that you wrote the original software.
// If you use this software in a product, an acknowledgment
// in the product documentation would be appreciated but is not required.
//
// 2. Altered source versions must be plainly marked as such,
// and must not be misrepresented as being the original software.
//
// 3. This notice may not be removed or altered from any source distribution.
//
////////////////////////////////////////////////////////////
#pragma once
////////////////////////////////////////////////////////////
// Headers
////////////////////////////////////////////////////////////
#include <SFML/System/Vector2.hpp>
#include <SFML/System/Vector3.hpp>
#include <cstddef>
namespace sf
{
namespace priv
{
// Forward declarations
template <std::size_t Columns, std::size_t Rows>
struct Matrix;
template <typename T>
struct Vector4;
} // namespace priv
////////////////////////////////////////////////////////////
/// \brief Namespace with GLSL types
///
////////////////////////////////////////////////////////////
namespace Glsl
{
////////////////////////////////////////////////////////////
/// \brief 2D float vector (\p vec2 in GLSL)
///
////////////////////////////////////////////////////////////
using Vec2 = Vector2<float>;
////////////////////////////////////////////////////////////
/// \brief 2D int vector (\p ivec2 in GLSL)
///
////////////////////////////////////////////////////////////
using Ivec2 = Vector2<int>;
////////////////////////////////////////////////////////////
/// \brief 2D bool vector (\p bvec2 in GLSL)
///
////////////////////////////////////////////////////////////
using Bvec2 = Vector2<bool>;
////////////////////////////////////////////////////////////
/// \brief 3D float vector (\p vec3 in GLSL)
///
////////////////////////////////////////////////////////////
using Vec3 = Vector3<float>;
////////////////////////////////////////////////////////////
/// \brief 3D int vector (\p ivec3 in GLSL)
///
////////////////////////////////////////////////////////////
using Ivec3 = Vector3<int>;
////////////////////////////////////////////////////////////
/// \brief 3D bool vector (\p bvec3 in GLSL)
///
////////////////////////////////////////////////////////////
using Bvec3 = Vector3<bool>;
#ifdef SFML_DOXYGEN
////////////////////////////////////////////////////////////
/// \brief 4D float vector (\p vec4 in GLSL)
///
/// 4D float vectors can be implicitly converted from `sf::Color`
/// instances. Each color channel is normalized from integers
/// in [0, 255] to floating point values in [0, 1].
/// \code
/// sf::Glsl::Vec4 zeroVector;
/// sf::Glsl::Vec4 vector(1.f, 2.f, 3.f, 4.f);
/// sf::Glsl::Vec4 color = sf::Color::Cyan;
/// \endcode
////////////////////////////////////////////////////////////
using Vec4 = ImplementationDefined;
////////////////////////////////////////////////////////////
/// \brief 4D int vector (\p ivec4 in GLSL)
///
/// 4D int vectors can be implicitly converted from `sf::Color`
/// instances. Each color channel remains unchanged inside
/// the integer interval [0, 255].
/// \code
/// sf::Glsl::Ivec4 zeroVector;
/// sf::Glsl::Ivec4 vector(1, 2, 3, 4);
/// sf::Glsl::Ivec4 color = sf::Color::Cyan;
/// \endcode
////////////////////////////////////////////////////////////
using Ivec4 = ImplementationDefined;
////////////////////////////////////////////////////////////
/// \brief 4D bool vector (\p bvec4 in GLSL)
///
////////////////////////////////////////////////////////////
using Bvec4 = ImplementationDefined;
////////////////////////////////////////////////////////////
/// \brief 3x3 float matrix (\p mat3 in GLSL)
///
/// The matrix can be constructed from an array with 3x3
/// elements, aligned in column-major order. For example,
/// a translation by (x, y) looks as follows:
/// \code
/// float array[9] =
/// {
/// 1, 0, 0,
/// 0, 1, 0,
/// x, y, 1
/// };
///
/// sf::Glsl::Mat3 matrix(array);
/// \endcode
///
/// Mat3 can also be implicitly converted from `sf::Transform`:
/// \code
/// sf::Transform transform;
/// sf::Glsl::Mat3 matrix = transform;
/// \endcode
////////////////////////////////////////////////////////////
using Mat3 = ImplementationDefined;
////////////////////////////////////////////////////////////
/// \brief 4x4 float matrix (\p mat4 in GLSL)
///
/// The matrix can be constructed from an array with 4x4
/// elements, aligned in column-major order. For example,
/// a translation by (x, y, z) looks as follows:
/// \code
/// float array[16] =
/// {
/// 1, 0, 0, 0,
/// 0, 1, 0, 0,
/// 0, 0, 1, 0,
/// x, y, z, 1
/// };
///
/// sf::Glsl::Mat4 matrix(array);
/// \endcode
///
/// Mat4 can also be implicitly converted from `sf::Transform`:
/// \code
/// sf::Transform transform;
/// sf::Glsl::Mat4 matrix = transform;
/// \endcode
////////////////////////////////////////////////////////////
using Mat4 = ImplementationDefined;
#else // SFML_DOXYGEN
using Vec4 = priv::Vector4<float>;
using Ivec4 = priv::Vector4<int>;
using Bvec4 = priv::Vector4<bool>;
using Mat3 = priv::Matrix<3, 3>;
using Mat4 = priv::Matrix<4, 4>;
#endif // SFML_DOXYGEN
} // namespace Glsl
} // namespace sf
#include <SFML/Graphics/Glsl.inl>
////////////////////////////////////////////////////////////
/// \namespace sf::Glsl
/// \ingroup graphics
///
/// \details The `sf::Glsl` namespace contains types that match
/// their equivalents in GLSL, the OpenGL shading language.
/// These types are exclusively used by the `sf::Shader` class.
///
/// Types that already exist in SFML, such as `sf::Vector2<T>`
/// and `sf::Vector3<T>`, are reused as type aliases, so you
/// can use the types in this namespace as well as the original ones.
/// Others are newly defined, such as `Glsl::Vec4` or `Glsl::Mat3`.
/// Their actual type is an implementation detail and should not be used.
///
/// All vector types support a default constructor that
/// initializes every component to zero, in addition to a
/// constructor with one parameter for each component.
/// The components are stored in member variables called
/// x, y, z, and w.
///
/// All matrix types support a constructor with a `float*`
/// parameter that points to a float array of the appropriate
/// size (that is, 9 in a 3x3 matrix, 16 in a 4x4 matrix).
/// Furthermore, they can be converted from `sf::Transform`
/// objects.
///
/// \see `sf::Shader`
///
////////////////////////////////////////////////////////////

View File

@ -1,177 +0,0 @@
////////////////////////////////////////////////////////////
//
// SFML - Simple and Fast Multimedia Library
// Copyright (C) 2007-2025 Laurent Gomila (laurent@sfml-dev.org)
//
// This software is provided 'as-is', without any express or implied warranty.
// In no event will the authors be held liable for any damages arising from the use of this software.
//
// Permission is granted to anyone to use this software for any purpose,
// including commercial applications, and to alter it and redistribute it freely,
// subject to the following restrictions:
//
// 1. The origin of this software must not be misrepresented;
// you must not claim that you wrote the original software.
// If you use this software in a product, an acknowledgment
// in the product documentation would be appreciated but is not required.
//
// 2. Altered source versions must be plainly marked as such,
// and must not be misrepresented as being the original software.
//
// 3. This notice may not be removed or altered from any source distribution.
//
////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////
// Headers
////////////////////////////////////////////////////////////
#include <SFML/Graphics/Export.hpp>
#include <SFML/Graphics/Color.hpp>
#include <SFML/Graphics/Glsl.hpp> // NOLINT(misc-header-include-cycle)
#include <array>
#include <cstddef>
namespace sf
{
class Transform;
} // namespace sf
namespace sf::priv
{
////////////////////////////////////////////////////////////
/// \brief Helper functions to copy `sf::Transform` to `sf::Glsl::Mat3/4`
///
////////////////////////////////////////////////////////////
void SFML_GRAPHICS_API copyMatrix(const Transform& source, Matrix<3, 3>& dest);
void SFML_GRAPHICS_API copyMatrix(const Transform& source, Matrix<4, 4>& dest);
////////////////////////////////////////////////////////////
/// \brief Copy array-based matrix with given number of elements
///
/// Indirection to `std::copy()` to avoid inclusion of
/// <algorithm> and MSVC's annoying 4996 warning in header
///
////////////////////////////////////////////////////////////
void SFML_GRAPHICS_API copyMatrix(const float* source, std::size_t elements, float* dest);
////////////////////////////////////////////////////////////
/// \brief Matrix type, used to set uniforms in GLSL
///
////////////////////////////////////////////////////////////
template <std::size_t Columns, std::size_t Rows>
struct Matrix
{
////////////////////////////////////////////////////////////
/// \brief Construct from raw data
///
/// \param pointer Points to the beginning of an array that
/// has the size of the matrix. The elements
/// are copied to the instance.
///
////////////////////////////////////////////////////////////
explicit Matrix(const float* pointer)
{
copyMatrix(pointer, Columns * Rows, array.data());
}
////////////////////////////////////////////////////////////
/// \brief Construct implicitly from SFML transform
///
/// This constructor is only supported for 3x3 and 4x4
/// matrices.
///
/// \param transform Object containing a transform.
///
////////////////////////////////////////////////////////////
Matrix(const Transform& transform)
{
copyMatrix(transform, *this);
}
std::array<float, Columns * Rows> array{}; //!< Array holding matrix data
};
////////////////////////////////////////////////////////////
/// \brief 4D vector type, used to set uniforms in GLSL
///
////////////////////////////////////////////////////////////
template <typename T>
struct Vector4
{
////////////////////////////////////////////////////////////
/// \brief Default constructor, creates a zero vector
///
////////////////////////////////////////////////////////////
constexpr Vector4() = default;
////////////////////////////////////////////////////////////
/// \brief Construct from 4 vector components
///
/// \param x Component of the 4D vector
/// \param y Component of the 4D vector
/// \param z Component of the 4D vector
/// \param w Component of the 4D vector
///
////////////////////////////////////////////////////////////
#if defined(__GNUC__)
#pragma GCC diagnostic push
#pragma GCC diagnostic ignored "-Wshadow"
#endif
constexpr Vector4(T x, T y, T z, T w) : x(x), y(y), z(z), w(w)
{
}
#if defined(__GNUC__)
#pragma GCC diagnostic pop
#endif
////////////////////////////////////////////////////////////
/// \brief Converts the vector to another type of vector
///
////////////////////////////////////////////////////////////
template <typename U>
constexpr explicit operator Vector4<U>() const
{
return Vector4<U>(static_cast<U>(x), static_cast<U>(y), static_cast<U>(z), static_cast<U>(w));
}
////////////////////////////////////////////////////////////
/// \brief Construct vector implicitly from color
///
/// Vector is normalized to [0, 1] for floats, and left as-is
/// for ints. Not defined for other template arguments.
///
/// \param color Color instance
///
////////////////////////////////////////////////////////////
constexpr Vector4(Color color);
T x{}; //!< 1st component (X) of the 4D vector
T y{}; //!< 2nd component (Y) of the 4D vector
T z{}; //!< 3rd component (Z) of the 4D vector
T w{}; //!< 4th component (W) of the 4D vector
};
////////////////////////////////////////////////////////////
template <>
constexpr Vector4<float>::Vector4(Color color) :
x(color.r / 255.f),
y(color.g / 255.f),
z(color.b / 255.f),
w(color.a / 255.f)
{
}
////////////////////////////////////////////////////////////
template <>
constexpr Vector4<int>::Vector4(Color color) : x(color.r), y(color.g), z(color.b), w(color.a)
{
}
} // namespace sf::priv

View File

@ -1,67 +0,0 @@
////////////////////////////////////////////////////////////
//
// SFML - Simple and Fast Multimedia Library
// Copyright (C) 2007-2025 Laurent Gomila (laurent@sfml-dev.org)
//
// This software is provided 'as-is', without any express or implied warranty.
// In no event will the authors be held liable for any damages arising from the use of this software.
//
// Permission is granted to anyone to use this software for any purpose,
// including commercial applications, and to alter it and redistribute it freely,
// subject to the following restrictions:
//
// 1. The origin of this software must not be misrepresented;
// you must not claim that you wrote the original software.
// If you use this software in a product, an acknowledgment
// in the product documentation would be appreciated but is not required.
//
// 2. Altered source versions must be plainly marked as such,
// and must not be misrepresented as being the original software.
//
// 3. This notice may not be removed or altered from any source distribution.
//
////////////////////////////////////////////////////////////
#pragma once
////////////////////////////////////////////////////////////
// Headers
////////////////////////////////////////////////////////////
#include <SFML/Graphics/Export.hpp>
#include <SFML/Graphics/Rect.hpp>
namespace sf
{
////////////////////////////////////////////////////////////
/// \brief Structure describing a glyph
///
////////////////////////////////////////////////////////////
struct SFML_GRAPHICS_API Glyph
{
float advance{}; //!< Offset to move horizontally to the next character
int lsbDelta{}; //!< Left offset after forced autohint. Internally used by getKerning()
int rsbDelta{}; //!< Right offset after forced autohint. Internally used by getKerning()
FloatRect bounds; //!< Bounding rectangle of the glyph, in coordinates relative to the baseline
IntRect textureRect; //!< Texture coordinates of the glyph inside the font's texture
};
} // namespace sf
////////////////////////////////////////////////////////////
/// \struct sf::Glyph
/// \ingroup graphics
///
/// A glyph is the visual representation of a character.
///
/// The `sf::Glyph` structure provides the information needed
/// to handle the glyph:
/// \li its coordinates in the font's texture
/// \li its bounding rectangle
/// \li the offset to apply to get the starting position of the next glyph
///
/// \see `sf::Font`
///
////////////////////////////////////////////////////////////

View File

@ -1,417 +0,0 @@
////////////////////////////////////////////////////////////
//
// SFML - Simple and Fast Multimedia Library
// Copyright (C) 2007-2025 Laurent Gomila (laurent@sfml-dev.org)
//
// This software is provided 'as-is', without any express or implied warranty.
// In no event will the authors be held liable for any damages arising from the use of this software.
//
// Permission is granted to anyone to use this software for any purpose,
// including commercial applications, and to alter it and redistribute it freely,
// subject to the following restrictions:
//
// 1. The origin of this software must not be misrepresented;
// you must not claim that you wrote the original software.
// If you use this software in a product, an acknowledgment
// in the product documentation would be appreciated but is not required.
//
// 2. Altered source versions must be plainly marked as such,
// and must not be misrepresented as being the original software.
//
// 3. This notice may not be removed or altered from any source distribution.
//
////////////////////////////////////////////////////////////
#pragma once
////////////////////////////////////////////////////////////
// Headers
////////////////////////////////////////////////////////////
#include <SFML/Graphics/Export.hpp>
#include <SFML/Graphics/Color.hpp>
#include <SFML/Graphics/Rect.hpp>
#include <SFML/System/Vector2.hpp>
#include <filesystem>
#include <optional>
#include <string_view>
#include <vector>
#include <cstddef>
#include <cstdint>
namespace sf
{
class InputStream;
////////////////////////////////////////////////////////////
/// \brief Class for loading, manipulating and saving images
///
////////////////////////////////////////////////////////////
class SFML_GRAPHICS_API Image
{
public:
////////////////////////////////////////////////////////////
/// \brief Default constructor
///
/// Constructs an image with width 0 and height 0.
///
/// \see `resize`
///
////////////////////////////////////////////////////////////
Image() = default;
////////////////////////////////////////////////////////////
/// \brief Construct the image and fill it with a unique color
///
/// \param size Width and height of the image
/// \param color Fill color
///
////////////////////////////////////////////////////////////
explicit Image(Vector2u size, Color color = Color::Black);
////////////////////////////////////////////////////////////
/// \brief Construct the image from an array of pixels
///
/// The pixel array is assumed to contain 32-bits RGBA pixels,
/// and have the given `size`. If not, this is an undefined behavior.
/// If `pixels` is `nullptr`, an empty image is created.
///
/// \param size Width and height of the image
/// \param pixels Array of pixels to copy to the image
///
////////////////////////////////////////////////////////////
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 sf::Exception 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 sf::Exception 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 sf::Exception if loading was unsuccessful
///
/// \see `loadFromFile`, `loadFromMemory`, `loadFromStream`
///
////////////////////////////////////////////////////////////
explicit Image(InputStream& stream);
////////////////////////////////////////////////////////////
/// \brief Resize the image and fill it with a unique color
///
/// \param size Width and height of the image
/// \param color Fill color
///
////////////////////////////////////////////////////////////
void resize(Vector2u size, Color color = Color::Black);
////////////////////////////////////////////////////////////
/// \brief Resize the image from an array of pixels
///
/// The pixel array is assumed to contain 32-bits RGBA pixels,
/// and have the given `size`. If not, this is an undefined behavior.
/// If `pixels` is `nullptr`, an empty image is created.
///
/// \param size Width and height of the image
/// \param pixels Array of pixels to copy to the image
///
////////////////////////////////////////////////////////////
void resize(Vector2u size, const std::uint8_t* pixels);
////////////////////////////////////////////////////////////
/// \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 `true` if loading was successful
///
/// \see `loadFromMemory`, `loadFromStream`, `saveToFile`
///
////////////////////////////////////////////////////////////
[[nodiscard]] bool loadFromFile(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 `true` if loading was successful
///
/// \see `loadFromFile`, `loadFromStream`, `saveToMemory`
///
////////////////////////////////////////////////////////////
[[nodiscard]] bool loadFromMemory(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 `true` if loading was successful
///
/// \see `loadFromFile`, `loadFromMemory`
///
////////////////////////////////////////////////////////////
[[nodiscard]] bool loadFromStream(InputStream& stream);
////////////////////////////////////////////////////////////
/// \brief Save the image to a file on disk
///
/// The format of the image is automatically deduced from
/// the extension. The supported image formats are bmp, png,
/// tga and jpg. The destination file is overwritten
/// if it already exists. This function fails if the image is empty.
///
/// \param filename Path of the file to save
///
/// \return `true` if saving was successful
///
/// \see `saveToMemory`, `loadFromFile`
///
////////////////////////////////////////////////////////////
[[nodiscard]] bool saveToFile(const std::filesystem::path& filename) const;
////////////////////////////////////////////////////////////
/// \brief Save the image to a buffer in memory
///
/// The format of the image must be specified.
/// The supported image formats are bmp, png, tga and jpg.
/// This function fails if the image is empty, or if
/// the format was invalid.
///
/// \param format Encoding format to use
///
/// \return Buffer with encoded data if saving was successful,
/// otherwise `std::nullopt`
///
/// \see `saveToFile`, `loadFromMemory`
///
////////////////////////////////////////////////////////////
[[nodiscard]] std::optional<std::vector<std::uint8_t>> saveToMemory(std::string_view format) const;
////////////////////////////////////////////////////////////
/// \brief Return the size (width and height) of the image
///
/// \return Size of the image, in pixels
///
////////////////////////////////////////////////////////////
[[nodiscard]] Vector2u getSize() const;
////////////////////////////////////////////////////////////
/// \brief Create a transparency mask from a specified color-key
///
/// This function sets the alpha value of every pixel matching
/// the given color to `alpha` (0 by default), so that they
/// become transparent.
///
/// \param color Color to make transparent
/// \param alpha Alpha value to assign to transparent pixels
///
////////////////////////////////////////////////////////////
void createMaskFromColor(Color color, std::uint8_t alpha = 0);
////////////////////////////////////////////////////////////
/// \brief Copy pixels from another image onto this one
///
/// This function does a slow pixel copy and should not be
/// used intensively. It can be used to prepare a complex
/// static image from several others, but if you need this
/// kind of feature in real-time you'd better use `sf::RenderTexture`.
///
/// If `sourceRect` is empty, the whole image is copied.
/// If `applyAlpha` is set to `true`, alpha blending is
/// applied from the source pixels to the destination pixels
/// using the \b over operator. If it is `false`, the source
/// pixels are copied unchanged with their alpha value.
///
/// See https://en.wikipedia.org/wiki/Alpha_compositing for
/// details on the \b over operator.
///
/// Note that this function can fail if either image is invalid
/// (i.e. zero-sized width or height), or if `sourceRect` is
/// not within the boundaries of the `source` parameter, or
/// if the destination area is out of the boundaries of this image.
///
/// On failure, the destination image is left unchanged.
///
/// \param source Source image to copy
/// \param dest Coordinates of the destination position
/// \param sourceRect Sub-rectangle of the source image to copy
/// \param applyAlpha Should the copy take into account the source transparency?
///
/// \return `true` if the operation was successful, `false` otherwise
///
////////////////////////////////////////////////////////////
[[nodiscard]] bool copy(const Image& source, Vector2u dest, const IntRect& sourceRect = {}, bool applyAlpha = false);
////////////////////////////////////////////////////////////
/// \brief Change the color of a pixel
///
/// This function doesn't check the validity of the pixel
/// coordinates, using out-of-range values will result in
/// an undefined behavior.
///
/// \param coords Coordinates of pixel to change
/// \param color New color of the pixel
///
/// \see `getPixel`
///
////////////////////////////////////////////////////////////
void setPixel(Vector2u coords, Color color);
////////////////////////////////////////////////////////////
/// \brief Get the color of a pixel
///
/// This function doesn't check the validity of the pixel
/// coordinates, using out-of-range values will result in
/// an undefined behavior.
///
/// \param coords Coordinates of pixel to change
///
/// \return Color of the pixel at given coordinates
///
/// \see `setPixel`
///
////////////////////////////////////////////////////////////
[[nodiscard]] Color getPixel(Vector2u coords) const;
////////////////////////////////////////////////////////////
/// \brief Get a read-only pointer to the array of pixels
///
/// The returned value points to an array of RGBA pixels made of
/// 8 bit integer components. The size of the array is
/// `width * height * 4 (getSize().x * getSize().y * 4)`.
/// Warning: the returned pointer may become invalid if you
/// modify the image, so you should never store it for too long.
/// If the image is empty, a null pointer is returned.
///
/// \return Read-only pointer to the array of pixels
///
////////////////////////////////////////////////////////////
[[nodiscard]] const std::uint8_t* getPixelsPtr() const;
////////////////////////////////////////////////////////////
/// \brief Flip the image horizontally (left <-> right)
///
////////////////////////////////////////////////////////////
void flipHorizontally();
////////////////////////////////////////////////////////////
/// \brief Flip the image vertically (top <-> bottom)
///
////////////////////////////////////////////////////////////
void flipVertically();
private:
////////////////////////////////////////////////////////////
// Member data
////////////////////////////////////////////////////////////
Vector2u m_size; //!< Image size
std::vector<std::uint8_t> m_pixels; //!< Pixels of the image
};
} // namespace sf
////////////////////////////////////////////////////////////
/// \class sf::Image
/// \ingroup graphics
///
/// `sf::Image` is an abstraction to manipulate images
/// as bi-dimensional arrays of pixels. The class provides
/// functions to load, read, write and save pixels, as well
/// as many other useful functions.
///
/// `sf::Image` can handle a unique internal representation of
/// pixels, which is RGBA 32 bits. This means that a pixel
/// must be composed of 8 bit red, green, blue and alpha
/// 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 `loadFromMemory`) must use this
/// representation as well.
///
/// A `sf::Image` can be copied, but it is a heavy resource and
/// if possible you should always use [const] references to
/// pass or return them to avoid useless copies.
///
/// Usage example:
/// \code
/// // Load an image file from a file
/// const sf::Image background("background.jpg");
///
/// // Create a 20x20 image filled with black color
/// sf::Image image({20, 20}, sf::Color::Black);
///
/// // Copy background on image at position (10, 10)
/// if (!image.copy(background, {10, 10}))
/// return -1;
///
/// // Make the top-left pixel transparent
/// sf::Color color = image.getPixel({0, 0});
/// color.a = 0;
/// image.setPixel({0, 0}, color);
///
/// // Save the image to a file
/// if (!image.saveToFile("result.png"))
/// return -1;
/// \endcode
///
/// \see `sf::Texture`
///
////////////////////////////////////////////////////////////

View File

@ -1,48 +0,0 @@
////////////////////////////////////////////////////////////
//
// SFML - Simple and Fast Multimedia Library
// Copyright (C) 2007-2025 Laurent Gomila (laurent@sfml-dev.org)
//
// This software is provided 'as-is', without any express or implied warranty.
// In no event will the authors be held liable for any damages arising from the use of this software.
//
// Permission is granted to anyone to use this software for any purpose,
// including commercial applications, and to alter it and redistribute it freely,
// subject to the following restrictions:
//
// 1. The origin of this software must not be misrepresented;
// you must not claim that you wrote the original software.
// If you use this software in a product, an acknowledgment
// in the product documentation would be appreciated but is not required.
//
// 2. Altered source versions must be plainly marked as such,
// and must not be misrepresented as being the original software.
//
// 3. This notice may not be removed or altered from any source distribution.
//
////////////////////////////////////////////////////////////
#pragma once
namespace sf
{
////////////////////////////////////////////////////////////
/// \ingroup graphics
/// \brief Types of primitives that a `sf::VertexArray` can render
///
/// Points and lines have no area, therefore their thickness
/// will always be 1 pixel, regardless the current transform
/// and view.
///
////////////////////////////////////////////////////////////
enum class PrimitiveType
{
Points, //!< List of individual points
Lines, //!< List of individual lines
LineStrip, //!< List of connected lines, a point uses the previous point to form a line
Triangles, //!< List of individual triangles
TriangleStrip, //!< List of connected triangles, a point uses the two previous points to form a triangle
TriangleFan //!< List of connected triangles, a point uses the common center and the previous point to form a triangle
};
} // namespace sf

View File

@ -1,203 +0,0 @@
////////////////////////////////////////////////////////////
//
// SFML - Simple and Fast Multimedia Library
// Copyright (C) 2007-2025 Laurent Gomila (laurent@sfml-dev.org)
//
// This software is provided 'as-is', without any express or implied warranty.
// In no event will the authors be held liable for any damages arising from the use of this software.
//
// Permission is granted to anyone to use this software for any purpose,
// including commercial applications, and to alter it and redistribute it freely,
// subject to the following restrictions:
//
// 1. The origin of this software must not be misrepresented;
// you must not claim that you wrote the original software.
// If you use this software in a product, an acknowledgment
// in the product documentation would be appreciated but is not required.
//
// 2. Altered source versions must be plainly marked as such,
// and must not be misrepresented as being the original software.
//
// 3. This notice may not be removed or altered from any source distribution.
//
////////////////////////////////////////////////////////////
#pragma once
////////////////////////////////////////////////////////////
// Headers
////////////////////////////////////////////////////////////
#include <SFML/System/Vector2.hpp>
#include <optional>
namespace sf
{
////////////////////////////////////////////////////////////
/// \brief Utility class for manipulating 2D axis aligned rectangles
///
////////////////////////////////////////////////////////////
template <typename T>
class Rect
{
public:
////////////////////////////////////////////////////////////
/// \brief Default constructor
///
/// Creates an empty rectangle (it is equivalent to calling
/// `Rect({0, 0}, {0, 0})`).
///
////////////////////////////////////////////////////////////
constexpr Rect() = default;
////////////////////////////////////////////////////////////
/// \brief Construct the rectangle from position and size
///
/// Be careful, the last parameter is the size,
/// not the bottom-right corner!
///
/// \param position Position of the top-left corner of the rectangle
/// \param size Size of the rectangle
///
////////////////////////////////////////////////////////////
constexpr Rect(Vector2<T> position, Vector2<T> size);
////////////////////////////////////////////////////////////
/// \brief Converts the rectangle to another type of rectangle
///
////////////////////////////////////////////////////////////
template <typename U>
constexpr explicit operator Rect<U>() const;
////////////////////////////////////////////////////////////
/// \brief Check if a point is inside the rectangle's area
///
/// This check is non-inclusive. If the point lies on the
/// edge of the rectangle, this function will return `false`.
///
/// \param point Point to test
///
/// \return `true` if the point is inside, `false` otherwise
///
/// \see `findIntersection`
///
////////////////////////////////////////////////////////////
[[nodiscard]] constexpr bool contains(Vector2<T> point) const;
////////////////////////////////////////////////////////////
/// \brief Check the intersection between two rectangles
///
/// \param rectangle Rectangle to test
///
/// \return Intersection rectangle if intersecting, `std::nullopt` otherwise
///
/// \see `contains`
///
////////////////////////////////////////////////////////////
[[nodiscard]] constexpr std::optional<Rect<T>> findIntersection(const Rect<T>& rectangle) const;
////////////////////////////////////////////////////////////
/// \brief Get the position of the center of the rectangle
///
/// \return Center of rectangle
///
////////////////////////////////////////////////////////////
[[nodiscard]] constexpr Vector2<T> getCenter() const;
////////////////////////////////////////////////////////////
// Member data
////////////////////////////////////////////////////////////
Vector2<T> position{}; //!< Position of the top-left corner of the rectangle
Vector2<T> size{}; //!< Size of the rectangle
};
////////////////////////////////////////////////////////////
/// \relates Rect
/// \brief Overload of binary `operator==`
///
/// This operator compares strict equality between two rectangles.
///
/// \param lhs Left operand (a rectangle)
/// \param rhs Right operand (a rectangle)
///
/// \return `true` if \a lhs is equal to \a rhs
///
////////////////////////////////////////////////////////////
template <typename T>
[[nodiscard]] constexpr bool operator==(const Rect<T>& lhs, const Rect<T>& rhs);
////////////////////////////////////////////////////////////
/// \relates Rect
/// \brief Overload of binary `operator!=`
///
/// This operator compares strict difference between two rectangles.
///
/// \param lhs Left operand (a rectangle)
/// \param rhs Right operand (a rectangle)
///
/// \return `true` if \a lhs is not equal to \a rhs
///
////////////////////////////////////////////////////////////
template <typename T>
[[nodiscard]] constexpr bool operator!=(const Rect<T>& lhs, const Rect<T>& rhs);
// Create type aliases for the most common types
using IntRect = Rect<int>;
using FloatRect = Rect<float>;
} // namespace sf
#include <SFML/Graphics/Rect.inl>
////////////////////////////////////////////////////////////
/// \class sf::Rect
/// \ingroup graphics
///
/// A rectangle is defined by its top-left corner and its size.
/// It is a very simple class defined for convenience, so
/// its member variables (position and size) are public
/// and can be accessed directly, just like the vector classes
/// (`Vector2` and `Vector3`).
///
/// To keep things simple, `sf::Rect` doesn't define
/// functions to emulate the properties that are not directly
/// members (such as right, bottom, etc.), it rather
/// only provides intersection functions.
///
/// `sf::Rect` uses the usual rules for its boundaries:
/// \li The left and top edges are included in the rectangle's area
/// \li The right and bottom edges are excluded from the rectangle's area
///
/// This means that `sf::IntRect({0, 0}, {1, 1})` and `sf::IntRect({1, 1}, {1, 1})`
/// don't intersect.
///
/// `sf::Rect` is a template and may be used with any numeric type, but
/// for simplicity type aliases for the instantiations used by SFML are given:
/// \li `sf::Rect<int>` is `sf::IntRect`
/// \li `sf::Rect<float>` is `sf::FloatRect`
///
/// So that you don't have to care about the template syntax.
///
/// Usage example:
/// \code
/// // Define a rectangle, located at (0, 0) with a size of 20x5
/// sf::IntRect r1({0, 0}, {20, 5});
///
/// // Define another rectangle, located at (4, 2) with a size of 18x10
/// sf::Vector2i position(4, 2);
/// sf::Vector2i size(18, 10);
/// sf::IntRect r2(position, size);
///
/// // Test intersections with the point (3, 1)
/// bool b1 = r1.contains({3, 1}); // true
/// bool b2 = r2.contains({3, 1}); // false
///
/// // Test the intersection between r1 and r2
/// std::optional<sf::IntRect> result = r1.findIntersection(r2);
/// // result.has_value() == true
/// // result.value() == sf::IntRect({4, 2}, {16, 3})
/// \endcode
///
////////////////////////////////////////////////////////////

View File

@ -1,130 +0,0 @@
////////////////////////////////////////////////////////////
//
// SFML - Simple and Fast Multimedia Library
// Copyright (C) 2007-2025 Laurent Gomila (laurent@sfml-dev.org)
//
// This software is provided 'as-is', without any express or implied warranty.
// In no event will the authors be held liable for any damages arising from the use of this software.
//
// Permission is granted to anyone to use this software for any purpose,
// including commercial applications, and to alter it and redistribute it freely,
// subject to the following restrictions:
//
// 1. The origin of this software must not be misrepresented;
// you must not claim that you wrote the original software.
// If you use this software in a product, an acknowledgment
// in the product documentation would be appreciated but is not required.
//
// 2. Altered source versions must be plainly marked as such,
// and must not be misrepresented as being the original software.
//
// 3. This notice may not be removed or altered from any source distribution.
//
////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////
// Headers
////////////////////////////////////////////////////////////
#include <SFML/Graphics/Rect.hpp> // NOLINT(misc-header-include-cycle)
namespace sf
{
////////////////////////////////////////////////////////////
template <typename T>
constexpr Rect<T>::Rect(Vector2<T> thePosition, Vector2<T> theSize) : position(thePosition), size(theSize)
{
}
////////////////////////////////////////////////////////////
template <typename T>
template <typename U>
constexpr Rect<T>::operator Rect<U>() const
{
return Rect<U>(Vector2<U>(position), Vector2<U>(size));
}
////////////////////////////////////////////////////////////
template <typename T>
constexpr bool Rect<T>::contains(Vector2<T> point) const
{
// Not using 'std::min' and 'std::max' to avoid depending on '<algorithm>'
const auto min = [](T a, T b) { return (a < b) ? a : b; };
const auto max = [](T a, T b) { return (a < b) ? b : a; };
// Rectangles with negative dimensions are allowed, so we must handle them correctly
// Compute the real min and max of the rectangle on both axes
const T minX = min(position.x, static_cast<T>(position.x + size.x));
const T maxX = max(position.x, static_cast<T>(position.x + size.x));
const T minY = min(position.y, static_cast<T>(position.y + size.y));
const T maxY = max(position.y, static_cast<T>(position.y + size.y));
return (point.x >= minX) && (point.x < maxX) && (point.y >= minY) && (point.y < maxY);
}
////////////////////////////////////////////////////////////
template <typename T>
constexpr std::optional<Rect<T>> Rect<T>::findIntersection(const Rect<T>& rectangle) const
{
// Not using 'std::min' and 'std::max' to avoid depending on '<algorithm>'
const auto min = [](T a, T b) { return (a < b) ? a : b; };
const auto max = [](T a, T b) { return (a < b) ? b : a; };
// Rectangles with negative dimensions are allowed, so we must handle them correctly
// Compute the min and max of the first rectangle on both axes
const T r1MinX = min(position.x, static_cast<T>(position.x + size.x));
const T r1MaxX = max(position.x, static_cast<T>(position.x + size.x));
const T r1MinY = min(position.y, static_cast<T>(position.y + size.y));
const T r1MaxY = max(position.y, static_cast<T>(position.y + size.y));
// Compute the min and max of the second rectangle on both axes
const T r2MinX = min(rectangle.position.x, static_cast<T>(rectangle.position.x + rectangle.size.x));
const T r2MaxX = max(rectangle.position.x, static_cast<T>(rectangle.position.x + rectangle.size.x));
const T r2MinY = min(rectangle.position.y, static_cast<T>(rectangle.position.y + rectangle.size.y));
const T r2MaxY = max(rectangle.position.y, static_cast<T>(rectangle.position.y + rectangle.size.y));
// Compute the intersection boundaries
const T interLeft = max(r1MinX, r2MinX);
const T interTop = max(r1MinY, r2MinY);
const T interRight = min(r1MaxX, r2MaxX);
const T interBottom = min(r1MaxY, r2MaxY);
// If the intersection is valid (positive non zero area), then there is an intersection
if ((interLeft < interRight) && (interTop < interBottom))
{
return Rect<T>({interLeft, interTop}, {interRight - interLeft, interBottom - interTop});
}
return std::nullopt;
}
////////////////////////////////////////////////////////////
template <typename T>
constexpr Vector2<T> Rect<T>::getCenter() const
{
return position + size / T{2};
}
////////////////////////////////////////////////////////////
template <typename T>
constexpr bool operator==(const Rect<T>& lhs, const Rect<T>& rhs)
{
return (lhs.position == rhs.position) && (lhs.size == rhs.size);
}
////////////////////////////////////////////////////////////
template <typename T>
constexpr bool operator!=(const Rect<T>& lhs, const Rect<T>& rhs)
{
return !(lhs == rhs);
}
} // namespace sf

View File

@ -1,143 +0,0 @@
////////////////////////////////////////////////////////////
//
// SFML - Simple and Fast Multimedia Library
// Copyright (C) 2007-2025 Laurent Gomila (laurent@sfml-dev.org)
//
// This software is provided 'as-is', without any express or implied warranty.
// In no event will the authors be held liable for any damages arising from the use of this software.
//
// Permission is granted to anyone to use this software for any purpose,
// including commercial applications, and to alter it and redistribute it freely,
// subject to the following restrictions:
//
// 1. The origin of this software must not be misrepresented;
// you must not claim that you wrote the original software.
// If you use this software in a product, an acknowledgment
// in the product documentation would be appreciated but is not required.
//
// 2. Altered source versions must be plainly marked as such,
// and must not be misrepresented as being the original software.
//
// 3. This notice may not be removed or altered from any source distribution.
//
////////////////////////////////////////////////////////////
#pragma once
////////////////////////////////////////////////////////////
// Headers
////////////////////////////////////////////////////////////
#include <SFML/Graphics/Export.hpp>
#include <SFML/Graphics/Shape.hpp>
#include <SFML/System/Vector2.hpp>
#include <cstddef>
namespace sf
{
////////////////////////////////////////////////////////////
/// \brief Specialized shape representing a rectangle
///
////////////////////////////////////////////////////////////
class SFML_GRAPHICS_API RectangleShape : public Shape
{
public:
////////////////////////////////////////////////////////////
/// \brief Default constructor
///
/// \param size Size of the rectangle
///
////////////////////////////////////////////////////////////
explicit RectangleShape(Vector2f size = {});
////////////////////////////////////////////////////////////
/// \brief Set the size of the rectangle
///
/// \param size New size of the rectangle
///
/// \see `getSize`
///
////////////////////////////////////////////////////////////
void setSize(Vector2f size);
////////////////////////////////////////////////////////////
/// \brief Get the size of the rectangle
///
/// \return Size of the rectangle
///
/// \see `setSize`
///
////////////////////////////////////////////////////////////
[[nodiscard]] Vector2f getSize() const;
////////////////////////////////////////////////////////////
/// \brief Get the number of points defining the shape
///
/// \return Number of points of the shape. For rectangle
/// shapes, this number is always 4.
///
////////////////////////////////////////////////////////////
[[nodiscard]] std::size_t getPointCount() const override;
////////////////////////////////////////////////////////////
/// \brief Get a point of the rectangle
///
/// The returned point is in local coordinates, that is,
/// the shape's transforms (position, rotation, scale) are
/// not taken into account.
/// The result is undefined if `index` is out of the valid range.
///
/// \param index Index of the point to get, in range [0 .. 3]
///
/// \return `index`-th point of the shape
///
////////////////////////////////////////////////////////////
[[nodiscard]] Vector2f getPoint(std::size_t index) const override;
////////////////////////////////////////////////////////////
/// \brief Get the geometric center of the rectangle
///
/// The returned point is in local coordinates, that is,
/// the shape's transforms (position, rotation, scale) are
/// not taken into account.
///
/// \return The geometric center of the shape
///
////////////////////////////////////////////////////////////
[[nodiscard]] Vector2f getGeometricCenter() const override;
private:
////////////////////////////////////////////////////////////
// Member data
////////////////////////////////////////////////////////////
Vector2f m_size; //!< Size of the rectangle
};
} // namespace sf
////////////////////////////////////////////////////////////
/// \class sf::RectangleShape
/// \ingroup graphics
///
/// This class inherits all the functions of `sf::Transformable`
/// (position, rotation, scale, bounds, ...) as well as the
/// functions of `sf::Shape` (outline, color, texture, ...).
///
/// Usage example:
/// \code
/// sf::RectangleShape rectangle;
/// rectangle.setSize(sf::Vector2f(100, 50));
/// rectangle.setOutlineColor(sf::Color::Red);
/// rectangle.setOutlineThickness(5);
/// rectangle.setPosition({10, 20});
/// ...
/// window.draw(rectangle);
/// \endcode
///
/// \see `sf::Shape`, `sf::CircleShape`, `sf::ConvexShape`
///
////////////////////////////////////////////////////////////

View File

@ -1,191 +0,0 @@
////////////////////////////////////////////////////////////
//
// SFML - Simple and Fast Multimedia Library
// Copyright (C) 2007-2025 Laurent Gomila (laurent@sfml-dev.org)
//
// This software is provided 'as-is', without any express or implied warranty.
// In no event will the authors be held liable for any damages arising from the use of this software.
//
// Permission is granted to anyone to use this software for any purpose,
// including commercial applications, and to alter it and redistribute it freely,
// subject to the following restrictions:
//
// 1. The origin of this software must not be misrepresented;
// you must not claim that you wrote the original software.
// If you use this software in a product, an acknowledgment
// in the product documentation would be appreciated but is not required.
//
// 2. Altered source versions must be plainly marked as such,
// and must not be misrepresented as being the original software.
//
// 3. This notice may not be removed or altered from any source distribution.
//
////////////////////////////////////////////////////////////
#pragma once
////////////////////////////////////////////////////////////
// Headers
////////////////////////////////////////////////////////////
#include <SFML/Graphics/Export.hpp>
#include <SFML/Graphics/BlendMode.hpp>
#include <SFML/Graphics/CoordinateType.hpp>
#include <SFML/Graphics/StencilMode.hpp>
#include <SFML/Graphics/Transform.hpp>
namespace sf
{
class Shader;
class Texture;
////////////////////////////////////////////////////////////
/// \brief Define the states used for drawing to a `RenderTarget`
///
////////////////////////////////////////////////////////////
struct SFML_GRAPHICS_API RenderStates
{
////////////////////////////////////////////////////////////
/// \brief Default constructor
///
/// Constructing a default set of render states is equivalent
/// to using `sf::RenderStates::Default`.
/// The default set defines:
/// \li the `BlendAlpha` blend mode
/// \li the default `StencilMode` (no stencil)
/// \li the identity transform
/// \li a `nullptr` texture
/// \li a `nullptr` shader
///
////////////////////////////////////////////////////////////
RenderStates() = default;
////////////////////////////////////////////////////////////
/// \brief Construct a default set of render states with a custom blend mode
///
/// \param theBlendMode Blend mode to use
///
////////////////////////////////////////////////////////////
RenderStates(const BlendMode& theBlendMode);
////////////////////////////////////////////////////////////
/// \brief Construct a default set of render states with a custom stencil mode
///
/// \param theStencilMode Stencil mode to use
///
////////////////////////////////////////////////////////////
RenderStates(const StencilMode& theStencilMode);
////////////////////////////////////////////////////////////
/// \brief Construct a default set of render states with a custom transform
///
/// \param theTransform Transform to use
///
////////////////////////////////////////////////////////////
RenderStates(const Transform& theTransform);
////////////////////////////////////////////////////////////
/// \brief Construct a default set of render states with a custom texture
///
/// \param theTexture Texture to use
///
////////////////////////////////////////////////////////////
RenderStates(const Texture* theTexture);
////////////////////////////////////////////////////////////
/// \brief Construct a default set of render states with a custom shader
///
/// \param theShader Shader to use
///
////////////////////////////////////////////////////////////
RenderStates(const Shader* theShader);
////////////////////////////////////////////////////////////
/// \brief Construct a set of render states with all its attributes
///
/// \param theBlendMode Blend mode to use
/// \param theStencilMode Stencil mode to use
/// \param theTransform Transform to use
/// \param theCoordinateType Texture coordinate type to use
/// \param theTexture Texture to use
/// \param theShader Shader to use
///
////////////////////////////////////////////////////////////
RenderStates(const BlendMode& theBlendMode,
const StencilMode& theStencilMode,
const Transform& theTransform,
CoordinateType theCoordinateType,
const Texture* theTexture,
const Shader* theShader);
////////////////////////////////////////////////////////////
// Static member data
////////////////////////////////////////////////////////////
// NOLINTNEXTLINE(readability-identifier-naming)
static const RenderStates Default; //!< Special instance holding the default render states
////////////////////////////////////////////////////////////
// Member data
////////////////////////////////////////////////////////////
BlendMode blendMode{BlendAlpha}; //!< Blending mode
StencilMode stencilMode; //!< Stencil mode
Transform transform; //!< Transform
CoordinateType coordinateType{CoordinateType::Pixels}; //!< Texture coordinate type
const Texture* texture{}; //!< Texture
const Shader* shader{}; //!< Shader
};
} // namespace sf
////////////////////////////////////////////////////////////
/// \class sf::RenderStates
/// \ingroup graphics
///
/// There are six global states that can be applied to
/// the drawn objects:
/// \li the blend mode: how pixels of the object are blended with the background
/// \li the stencil mode: how pixels of the object interact with the stencil buffer
/// \li the transform: how the object is positioned/rotated/scaled
/// \li the texture coordinate type: how texture coordinates are interpreted
/// \li the texture: what image is mapped to the object
/// \li the shader: what custom effect is applied to the object
///
/// High-level objects such as sprites or text force some of
/// these states when they are drawn. For example, a sprite
/// will set its own texture, so that you don't have to care
/// about it when drawing the sprite.
///
/// The transform is a special case: sprites, texts and shapes
/// (and it's a good idea to do it with your own drawable classes
/// too) combine their transform with the one that is passed in the
/// RenderStates structure. So that you can use a "global" transform
/// on top of each object's transform.
///
/// Most objects, especially high-level drawables, can be drawn
/// directly without defining render states explicitly -- the
/// default set of states is ok in most cases.
/// \code
/// window.draw(sprite);
/// \endcode
///
/// If you want to use a single specific render state,
/// for example a shader, you can pass it directly to the Draw
/// function: `sf::RenderStates` has an implicit one-argument
/// constructor for each state.
/// \code
/// window.draw(sprite, shader);
/// \endcode
///
/// When you're inside the Draw function of a drawable
/// object (inherited from `sf::Drawable`), you can
/// either pass the render states unmodified, or change
/// some of them.
/// For example, a transformable object will combine the
/// current transform with its own transform. A sprite will
/// set its texture. Etc.
///
/// \see `sf::RenderTarget`, `sf::Drawable`
///
////////////////////////////////////////////////////////////

View File

@ -1,606 +0,0 @@
////////////////////////////////////////////////////////////
//
// SFML - Simple and Fast Multimedia Library
// Copyright (C) 2007-2025 Laurent Gomila (laurent@sfml-dev.org)
//
// This software is provided 'as-is', without any express or implied warranty.
// In no event will the authors be held liable for any damages arising from the use of this software.
//
// Permission is granted to anyone to use this software for any purpose,
// including commercial applications, and to alter it and redistribute it freely,
// subject to the following restrictions:
//
// 1. The origin of this software must not be misrepresented;
// you must not claim that you wrote the original software.
// If you use this software in a product, an acknowledgment
// in the product documentation would be appreciated but is not required.
//
// 2. Altered source versions must be plainly marked as such,
// and must not be misrepresented as being the original software.
//
// 3. This notice may not be removed or altered from any source distribution.
//
////////////////////////////////////////////////////////////
#pragma once
////////////////////////////////////////////////////////////
// Headers
////////////////////////////////////////////////////////////
#include <SFML/Graphics/Export.hpp>
#include <SFML/Graphics/BlendMode.hpp>
#include <SFML/Graphics/Color.hpp>
#include <SFML/Graphics/CoordinateType.hpp>
#include <SFML/Graphics/PrimitiveType.hpp>
#include <SFML/Graphics/Rect.hpp>
#include <SFML/Graphics/RenderStates.hpp>
#include <SFML/Graphics/StencilMode.hpp>
#include <SFML/Graphics/Vertex.hpp>
#include <SFML/Graphics/View.hpp>
#include <SFML/System/Vector2.hpp>
#include <array>
#include <cstddef>
#include <cstdint>
namespace sf
{
class Drawable;
class Shader;
class Texture;
class Transform;
class VertexBuffer;
////////////////////////////////////////////////////////////
/// \brief Base class for all render targets (window, texture, ...)
///
////////////////////////////////////////////////////////////
class SFML_GRAPHICS_API RenderTarget
{
public:
////////////////////////////////////////////////////////////
/// \brief Destructor
///
////////////////////////////////////////////////////////////
virtual ~RenderTarget() = default;
////////////////////////////////////////////////////////////
/// \brief Deleted copy constructor
///
////////////////////////////////////////////////////////////
RenderTarget(const RenderTarget&) = delete;
////////////////////////////////////////////////////////////
/// \brief Deleted copy assignment
///
////////////////////////////////////////////////////////////
RenderTarget& operator=(const RenderTarget&) = delete;
////////////////////////////////////////////////////////////
/// \brief Move constructor
///
////////////////////////////////////////////////////////////
RenderTarget(RenderTarget&&) noexcept = default;
////////////////////////////////////////////////////////////
/// \brief Move assignment
///
////////////////////////////////////////////////////////////
RenderTarget& operator=(RenderTarget&&) noexcept = default;
////////////////////////////////////////////////////////////
/// \brief Clear the entire target with a single color
///
/// This function is usually called once every frame,
/// to clear the previous contents of the target.
///
/// \param color Fill color to use to clear the render target
///
////////////////////////////////////////////////////////////
void clear(Color color = Color::Black);
////////////////////////////////////////////////////////////
/// \brief Clear the stencil buffer to a specific value
///
/// The specified value is truncated to the bit width of
/// the current stencil buffer.
///
/// \param stencilValue Stencil value to clear to
///
////////////////////////////////////////////////////////////
void clearStencil(StencilValue stencilValue);
////////////////////////////////////////////////////////////
/// \brief Clear the entire target with a single color and stencil value
///
/// The specified stencil value is truncated to the bit
/// width of the current stencil buffer.
///
/// \param color Fill color to use to clear the render target
/// \param stencilValue Stencil value to clear to
///
////////////////////////////////////////////////////////////
void clear(Color color, StencilValue stencilValue);
////////////////////////////////////////////////////////////
/// \brief Change the current active view
///
/// The view is like a 2D camera, it controls which part of
/// the 2D scene is visible, and how it is viewed in the
/// render target.
/// The new view will affect everything that is drawn, until
/// another view is set.
/// The render target keeps its own copy of the view object,
/// so it is not necessary to keep the original one alive
/// after calling this function.
/// To restore the original view of the target, you can pass
/// the result of `getDefaultView()` to this function.
///
/// \param view New view to use
///
/// \see `getView`, `getDefaultView`
///
////////////////////////////////////////////////////////////
void setView(const View& view);
////////////////////////////////////////////////////////////
/// \brief Get the view currently in use in the render target
///
/// \return The view object that is currently used
///
/// \see `setView`, `getDefaultView`
///
////////////////////////////////////////////////////////////
[[nodiscard]] const View& getView() const;
////////////////////////////////////////////////////////////
/// \brief Get the default view of the render target
///
/// The default view has the initial size of the render target,
/// and never changes after the target has been created.
///
/// \return The default view of the render target
///
/// \see `setView`, `getView`
///
////////////////////////////////////////////////////////////
[[nodiscard]] const View& getDefaultView() const;
////////////////////////////////////////////////////////////
/// \brief Get the viewport of a view, applied to this render target
///
/// The viewport is defined in the view as a ratio, this function
/// simply applies this ratio to the current dimensions of the
/// render target to calculate the pixels rectangle that the viewport
/// actually covers in the target.
///
/// \param view The view for which we want to compute the viewport
///
/// \return Viewport rectangle, expressed in pixels
///
////////////////////////////////////////////////////////////
[[nodiscard]] IntRect getViewport(const View& view) const;
////////////////////////////////////////////////////////////
/// \brief Get the scissor rectangle of a view, applied to this render target
///
/// The scissor rectangle is defined in the view as a ratio. This
/// function simply applies this ratio to the current dimensions
/// of the render target to calculate the pixels rectangle
/// that the scissor rectangle actually covers in the target.
///
/// \param view The view for which we want to compute the scissor rectangle
///
/// \return Scissor rectangle, expressed in pixels
///
////////////////////////////////////////////////////////////
[[nodiscard]] IntRect getScissor(const View& view) const;
////////////////////////////////////////////////////////////
/// \brief Convert a point from target coordinates to world
/// coordinates, using the current view
///
/// This function is an overload of the mapPixelToCoords
/// function that implicitly uses the current view.
/// It is equivalent to:
/// \code
/// target.mapPixelToCoords(point, target.getView());
/// \endcode
///
/// \param point Pixel to convert
///
/// \return The converted point, in "world" coordinates
///
/// \see `mapCoordsToPixel`
///
////////////////////////////////////////////////////////////
[[nodiscard]] Vector2f mapPixelToCoords(Vector2i point) const;
////////////////////////////////////////////////////////////
/// \brief Convert a point from target coordinates to world coordinates
///
/// This function finds the 2D position that matches the
/// given pixel of the render target. In other words, it does
/// the inverse of what the graphics card does, to find the
/// initial position of a rendered pixel.
///
/// Initially, both coordinate systems (world units and target pixels)
/// match perfectly. But if you define a custom view or resize your
/// render target, this assertion is not `true` anymore, i.e. a point
/// located at (10, 50) in your render target may map to the point
/// (150, 75) in your 2D world -- if the view is translated by (140, 25).
///
/// For render-windows, this function is typically used to find
/// which point (or object) is located below the mouse cursor.
///
/// This version uses a custom view for calculations, see the other
/// overload of the function if you want to use the current view of the
/// render target.
///
/// \param point Pixel to convert
/// \param view The view to use for converting the point
///
/// \return The converted point, in "world" units
///
/// \see `mapCoordsToPixel`
///
////////////////////////////////////////////////////////////
[[nodiscard]] Vector2f mapPixelToCoords(Vector2i point, const View& view) const;
////////////////////////////////////////////////////////////
/// \brief Convert a point from world coordinates to target
/// coordinates, using the current view
///
/// This function is an overload of the `mapCoordsToPixel`
/// function that implicitly uses the current view.
/// It is equivalent to:
/// \code
/// target.mapCoordsToPixel(point, target.getView());
/// \endcode
///
/// \param point Point to convert
///
/// \return The converted point, in target coordinates (pixels)
///
/// \see `mapPixelToCoords`
///
////////////////////////////////////////////////////////////
[[nodiscard]] Vector2i mapCoordsToPixel(Vector2f point) const;
////////////////////////////////////////////////////////////
/// \brief Convert a point from world coordinates to target coordinates
///
/// This function finds the pixel of the render target that matches
/// the given 2D point. In other words, it goes through the same process
/// as the graphics card, to compute the final position of a rendered point.
///
/// Initially, both coordinate systems (world units and target pixels)
/// match perfectly. But if you define a custom view or resize your
/// render target, this assertion is not `true` anymore, i.e. a point
/// located at (150, 75) in your 2D world may map to the pixel
/// (10, 50) of your render target -- if the view is translated by (140, 25).
///
/// This version uses a custom view for calculations, see the other
/// overload of the function if you want to use the current view of the
/// render target.
///
/// \param point Point to convert
/// \param view The view to use for converting the point
///
/// \return The converted point, in target coordinates (pixels)
///
/// \see `mapPixelToCoords`
///
////////////////////////////////////////////////////////////
[[nodiscard]] Vector2i mapCoordsToPixel(Vector2f point, const View& view) const;
////////////////////////////////////////////////////////////
/// \brief Draw a drawable object to the render target
///
/// \param drawable Object to draw
/// \param states Render states to use for drawing
///
////////////////////////////////////////////////////////////
void draw(const Drawable& drawable, const RenderStates& states = RenderStates::Default);
////////////////////////////////////////////////////////////
/// \brief Draw primitives defined by an array of vertices
///
/// \param vertices Pointer to the vertices
/// \param vertexCount Number of vertices in the array
/// \param type Type of primitives to draw
/// \param states Render states to use for drawing
///
////////////////////////////////////////////////////////////
void draw(const Vertex* vertices,
std::size_t vertexCount,
PrimitiveType type,
const RenderStates& states = RenderStates::Default);
////////////////////////////////////////////////////////////
/// \brief Draw primitives defined by a vertex buffer
///
/// \param vertexBuffer Vertex buffer
/// \param states Render states to use for drawing
///
////////////////////////////////////////////////////////////
void draw(const VertexBuffer& vertexBuffer, const RenderStates& states = RenderStates::Default);
////////////////////////////////////////////////////////////
/// \brief Draw primitives defined by a vertex buffer
///
/// \param vertexBuffer Vertex buffer
/// \param firstVertex Index of the first vertex to render
/// \param vertexCount Number of vertices to render
/// \param states Render states to use for drawing
///
////////////////////////////////////////////////////////////
void draw(const VertexBuffer& vertexBuffer,
std::size_t firstVertex,
std::size_t vertexCount,
const RenderStates& states = RenderStates::Default);
////////////////////////////////////////////////////////////
/// \brief Return the size of the rendering region of the target
///
/// \return Size in pixels
///
////////////////////////////////////////////////////////////
[[nodiscard]] virtual Vector2u getSize() const = 0;
////////////////////////////////////////////////////////////
/// \brief Tell if the render target will use sRGB encoding when drawing on it
///
/// \return `true` if the render target use sRGB encoding, `false` otherwise
///
////////////////////////////////////////////////////////////
[[nodiscard]] virtual bool isSrgb() const;
////////////////////////////////////////////////////////////
/// \brief Activate or deactivate the render target for rendering
///
/// This function makes the render target's context current for
/// future OpenGL rendering operations (so you shouldn't care
/// about it if you're not doing direct OpenGL stuff).
/// A render target's context is active only on the current thread,
/// if you want to make it active on another thread you have
/// to deactivate it on the previous thread first if it was active.
/// Only one context can be current in a thread, so if you
/// want to draw OpenGL geometry to another render target
/// don't forget to activate it again. Activating a render
/// target will automatically deactivate the previously active
/// context (if any).
///
/// \param active `true` to activate, `false` to deactivate
///
/// \return `true` if operation was successful, `false` otherwise
///
////////////////////////////////////////////////////////////
[[nodiscard]] virtual bool setActive(bool active = true);
////////////////////////////////////////////////////////////
/// \brief Save the current OpenGL render states and matrices
///
/// This function can be used when you mix SFML drawing
/// and direct OpenGL rendering. Combined with popGLStates,
/// it ensures that:
/// \li SFML's internal states are not messed up by your OpenGL code
/// \li your OpenGL states are not modified by a call to a SFML function
///
/// More specifically, it must be used around code that
/// calls `draw` functions. Example:
/// \code
/// // OpenGL code here...
/// window.pushGLStates();
/// window.draw(...);
/// window.draw(...);
/// window.popGLStates();
/// // OpenGL code here...
/// \endcode
///
/// Note that this function is quite expensive: it saves all the
/// possible OpenGL states and matrices, even the ones you
/// don't care about. Therefore it should be used wisely.
/// It is provided for convenience, but the best results will
/// be achieved if you handle OpenGL states yourself (because
/// you know which states have really changed, and need to be
/// saved and restored). Take a look at the resetGLStates
/// function if you do so.
///
/// \see `popGLStates`
///
////////////////////////////////////////////////////////////
void pushGLStates();
////////////////////////////////////////////////////////////
/// \brief Restore the previously saved OpenGL render states and matrices
///
/// See the description of `pushGLStates` to get a detailed
/// description of these functions.
///
/// \see `pushGLStates`
///
////////////////////////////////////////////////////////////
void popGLStates();
////////////////////////////////////////////////////////////
/// \brief Reset the internal OpenGL states so that the target is ready for drawing
///
/// This function can be used when you mix SFML drawing
/// and direct OpenGL rendering, if you choose not to use
/// `pushGLStates`/`popGLStates`. It makes sure that all OpenGL
/// states needed by SFML are set, so that subsequent `draw()`
/// calls will work as expected.
///
/// Example:
/// \code
/// // OpenGL code here...
/// glPushAttrib(...);
/// window.resetGLStates();
/// window.draw(...);
/// window.draw(...);
/// glPopAttrib(...);
/// // OpenGL code here...
/// \endcode
///
////////////////////////////////////////////////////////////
void resetGLStates();
protected:
////////////////////////////////////////////////////////////
/// \brief Default constructor
///
////////////////////////////////////////////////////////////
RenderTarget() = default;
////////////////////////////////////////////////////////////
/// \brief Performs the common initialization step after creation
///
/// The derived classes must call this function after the
/// target is created and ready for drawing.
///
////////////////////////////////////////////////////////////
void initialize();
private:
////////////////////////////////////////////////////////////
/// \brief Apply the current view
///
////////////////////////////////////////////////////////////
void applyCurrentView();
////////////////////////////////////////////////////////////
/// \brief Apply a new blending mode
///
/// \param mode Blending mode to apply
///
////////////////////////////////////////////////////////////
void applyBlendMode(const BlendMode& mode);
////////////////////////////////////////////////////////////
/// \brief Apply a new stencil mode
///
/// \param mode Stencil mode to apply
///
////////////////////////////////////////////////////////////
void applyStencilMode(const StencilMode& mode);
////////////////////////////////////////////////////////////
/// \brief Apply a new transform
///
/// \param transform Transform to apply
///
////////////////////////////////////////////////////////////
void applyTransform(const Transform& transform);
////////////////////////////////////////////////////////////
/// \brief Apply a new texture
///
/// \param texture Texture to apply
/// \param coordinateType The texture coordinate type to use
///
////////////////////////////////////////////////////////////
void applyTexture(const Texture* texture, CoordinateType coordinateType = CoordinateType::Pixels);
////////////////////////////////////////////////////////////
/// \brief Apply a new shader
///
/// \param shader Shader to apply
///
////////////////////////////////////////////////////////////
void applyShader(const Shader* shader);
////////////////////////////////////////////////////////////
/// \brief Setup environment for drawing
///
/// \param useVertexCache Are we going to use the vertex cache?
/// \param states Render states to use for drawing
///
////////////////////////////////////////////////////////////
void setupDraw(bool useVertexCache, const RenderStates& states);
////////////////////////////////////////////////////////////
/// \brief Draw the primitives
///
/// \param type Type of primitives to draw
/// \param firstVertex Index of the first vertex to use when drawing
/// \param vertexCount Number of vertices to use when drawing
///
////////////////////////////////////////////////////////////
void drawPrimitives(PrimitiveType type, std::size_t firstVertex, std::size_t vertexCount);
////////////////////////////////////////////////////////////
/// \brief Clean up environment after drawing
///
/// \param states Render states used for drawing
///
////////////////////////////////////////////////////////////
void cleanupDraw(const RenderStates& states);
////////////////////////////////////////////////////////////
/// \brief Render states cache
///
////////////////////////////////////////////////////////////
struct StatesCache
{
bool enable{}; //!< Is the cache enabled?
bool glStatesSet{}; //!< Are our internal GL states set yet?
bool viewChanged{}; //!< Has the current view changed since last draw?
bool scissorEnabled{}; //!< Is scissor testing enabled?
bool stencilEnabled{}; //!< Is stencil testing enabled?
BlendMode lastBlendMode; //!< Cached blending mode
StencilMode lastStencilMode; //!< Cached stencil
std::uint64_t lastTextureId{}; //!< Cached texture
CoordinateType lastCoordinateType{}; //!< Texture coordinate type
bool texCoordsArrayEnabled{}; //!< Is `GL_TEXTURE_COORD_ARRAY` client state enabled?
bool useVertexCache{}; //!< Did we previously use the vertex cache?
std::array<Vertex, 4> vertexCache{}; //!< Pre-transformed vertices cache
};
////////////////////////////////////////////////////////////
// Member data
////////////////////////////////////////////////////////////
View m_defaultView; //!< Default view
View m_view; //!< Current view
StatesCache m_cache{}; //!< Render states cache
std::uint64_t m_id{}; //!< Unique number that identifies the RenderTarget
};
} // namespace sf
////////////////////////////////////////////////////////////
/// \class sf::RenderTarget
/// \ingroup graphics
///
/// `sf::RenderTarget` defines the common behavior of all the
/// 2D render targets usable in the graphics module. It makes
/// it possible to draw 2D entities like sprites, shapes, text
/// without using any OpenGL command directly.
///
/// A `sf::RenderTarget` is also able to use views (`sf::View`),
/// which are a kind of 2D cameras. With views you can globally
/// scroll, rotate or zoom everything that is drawn,
/// without having to transform every single entity. See the
/// documentation of `sf::View` for more details and sample pieces of
/// code about this class.
///
/// On top of that, render targets are still able to render direct
/// OpenGL stuff. It is even possible to mix together OpenGL calls
/// and regular SFML drawing commands. When doing so, make sure that
/// OpenGL states are not messed up by calling the
/// `pushGLStates`/`popGLStates` functions.
///
/// While render targets are moveable, it is not valid to move them
/// between threads. This will cause your program to crash. The
/// problem boils down to OpenGL being limited with regard to how it
/// works in multithreaded environments. Please ensure you only move
/// render targets within the same thread.
///
/// \see `sf::RenderWindow`, `sf::RenderTexture`, `sf::View`
///
////////////////////////////////////////////////////////////

View File

@ -1,342 +0,0 @@
////////////////////////////////////////////////////////////
//
// SFML - Simple and Fast Multimedia Library
// Copyright (C) 2007-2025 Laurent Gomila (laurent@sfml-dev.org)
//
// This software is provided 'as-is', without any express or implied warranty.
// In no event will the authors be held liable for any damages arising from the use of this software.
//
// Permission is granted to anyone to use this software for any purpose,
// including commercial applications, and to alter it and redistribute it freely,
// subject to the following restrictions:
//
// 1. The origin of this software must not be misrepresented;
// you must not claim that you wrote the original software.
// If you use this software in a product, an acknowledgment
// in the product documentation would be appreciated but is not required.
//
// 2. Altered source versions must be plainly marked as such,
// and must not be misrepresented as being the original software.
//
// 3. This notice may not be removed or altered from any source distribution.
//
////////////////////////////////////////////////////////////
#pragma once
////////////////////////////////////////////////////////////
// Headers
////////////////////////////////////////////////////////////
#include <SFML/Graphics/Export.hpp>
#include <SFML/Graphics/RenderTarget.hpp>
#include <SFML/Graphics/Texture.hpp>
#include <SFML/Window/ContextSettings.hpp>
#include <SFML/System/Vector2.hpp>
#include <memory>
namespace sf
{
namespace priv
{
class RenderTextureImpl;
}
////////////////////////////////////////////////////////////
/// \brief Target for off-screen 2D rendering into a texture
///
////////////////////////////////////////////////////////////
class SFML_GRAPHICS_API RenderTexture : public RenderTarget
{
public:
////////////////////////////////////////////////////////////
/// \brief Default constructor
///
/// Constructs a render-texture with width 0 and height 0.
///
/// \see `resize`
///
////////////////////////////////////////////////////////////
RenderTexture();
////////////////////////////////////////////////////////////
/// \brief Construct a render-texture
///
/// The last parameter, `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 sf::Exception if creation was unsuccessful
///
////////////////////////////////////////////////////////////
RenderTexture(Vector2u size, const ContextSettings& settings = {});
////////////////////////////////////////////////////////////
/// \brief Destructor
///
////////////////////////////////////////////////////////////
~RenderTexture() override;
////////////////////////////////////////////////////////////
/// \brief Deleted copy constructor
///
////////////////////////////////////////////////////////////
RenderTexture(const RenderTexture&) = delete;
////////////////////////////////////////////////////////////
/// \brief Deleted copy assignment
///
////////////////////////////////////////////////////////////
RenderTexture& operator=(const RenderTexture&) = delete;
////////////////////////////////////////////////////////////
/// \brief Move constructor
///
////////////////////////////////////////////////////////////
RenderTexture(RenderTexture&&) noexcept;
////////////////////////////////////////////////////////////
/// \brief Move assignment operator
///
////////////////////////////////////////////////////////////
RenderTexture& operator=(RenderTexture&&) noexcept;
////////////////////////////////////////////////////////////
/// \brief Resize the render-texture
///
/// The last parameter, `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 resizing, 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 `true` if resizing has been successful, `false` if it failed
///
////////////////////////////////////////////////////////////
[[nodiscard]] bool resize(Vector2u size, const ContextSettings& settings = {});
////////////////////////////////////////////////////////////
/// \brief Get the maximum anti-aliasing level supported by the system
///
/// \return The maximum anti-aliasing level supported by the system
///
////////////////////////////////////////////////////////////
[[nodiscard]] static unsigned int getMaximumAntiAliasingLevel();
////////////////////////////////////////////////////////////
/// \brief Enable or disable texture smoothing
///
/// This function is similar to `Texture::setSmooth`.
/// This parameter is disabled by default.
///
/// \param smooth `true` to enable smoothing, `false` to disable it
///
/// \see `isSmooth`
///
////////////////////////////////////////////////////////////
void setSmooth(bool smooth);
////////////////////////////////////////////////////////////
/// \brief Tell whether the smooth filtering is enabled or not
///
/// \return `true` if texture smoothing is enabled
///
/// \see `setSmooth`
///
////////////////////////////////////////////////////////////
[[nodiscard]] bool isSmooth() const;
////////////////////////////////////////////////////////////
/// \brief Enable or disable texture repeating
///
/// This function is similar to `Texture::setRepeated`.
/// This parameter is disabled by default.
///
/// \param repeated `true` to enable repeating, `false` to disable it
///
/// \see `isRepeated`
///
////////////////////////////////////////////////////////////
void setRepeated(bool repeated);
////////////////////////////////////////////////////////////
/// \brief Tell whether the texture is repeated or not
///
/// \return `true` if texture is repeated
///
/// \see `setRepeated`
///
////////////////////////////////////////////////////////////
[[nodiscard]] bool isRepeated() const;
////////////////////////////////////////////////////////////
/// \brief Generate a mipmap using the current texture data
///
/// This function is similar to `Texture::generateMipmap` and operates
/// on the texture used as the target for drawing.
/// Be aware that any draw operation may modify the base level image data.
/// For this reason, calling this function only makes sense after all
/// drawing is completed and display has been called. Not calling display
/// after subsequent drawing will lead to undefined behavior if a mipmap
/// had been previously generated.
///
/// \return `true` if mipmap generation was successful, `false` if unsuccessful
///
////////////////////////////////////////////////////////////
[[nodiscard]] bool generateMipmap();
////////////////////////////////////////////////////////////
/// \brief Activate or deactivate the render-texture for rendering
///
/// This function makes the render-texture's context current for
/// future OpenGL rendering operations (so you shouldn't care
/// about it if you're not doing direct OpenGL stuff).
/// Only one context can be current in a thread, so if you
/// want to draw OpenGL geometry to another render target
/// (like a RenderWindow) don't forget to activate it again.
///
/// \param active `true` to activate, `false` to deactivate
///
/// \return `true` if operation was successful, `false` otherwise
///
////////////////////////////////////////////////////////////
[[nodiscard]] bool setActive(bool active = true) override;
////////////////////////////////////////////////////////////
/// \brief Update the contents of the target texture
///
/// This function updates the target texture with what
/// has been drawn so far. Like for windows, calling this
/// function is mandatory at the end of rendering. Not calling
/// it may leave the texture in an undefined state.
///
////////////////////////////////////////////////////////////
void display();
////////////////////////////////////////////////////////////
/// \brief Return the size of the rendering region of the texture
///
/// The returned value is the size that you passed to
/// the create function.
///
/// \return Size in pixels
///
////////////////////////////////////////////////////////////
[[nodiscard]] Vector2u getSize() const override;
////////////////////////////////////////////////////////////
/// \brief Tell if the render-texture will use sRGB encoding when drawing on it
///
/// You can request sRGB encoding for a render-texture
/// by having the sRgbCapable flag set for the context parameter of `create()` method
///
/// \return `true` if the render-texture use sRGB encoding, `false` otherwise
///
////////////////////////////////////////////////////////////
[[nodiscard]] bool isSrgb() const override;
////////////////////////////////////////////////////////////
/// \brief Get a read-only reference to the target texture
///
/// After drawing to the render-texture and calling Display,
/// you can retrieve the updated texture using this function,
/// and draw it using a sprite (for example).
/// The internal `sf::Texture` of a render-texture is always the
/// same instance, so that it is possible to call this function
/// once and keep a reference to the texture even after it is
/// modified.
///
/// \return Const reference to the texture
///
////////////////////////////////////////////////////////////
[[nodiscard]] const Texture& getTexture() const;
private:
////////////////////////////////////////////////////////////
// Member data
////////////////////////////////////////////////////////////
std::unique_ptr<priv::RenderTextureImpl> m_impl; //!< Platform/hardware specific implementation
Texture m_texture; //!< Target texture to draw on
};
} // namespace sf
////////////////////////////////////////////////////////////
/// \class sf::RenderTexture
/// \ingroup graphics
///
/// `sf::RenderTexture` is the little brother of `sf::RenderWindow`.
/// It implements the same 2D drawing and OpenGL-related functions
/// (see their base class `sf::RenderTarget` for more details),
/// the difference is that the result is stored in an off-screen
/// texture rather than being show in a window.
///
/// Rendering to a texture can be useful in a variety of situations:
/// \li precomputing a complex static texture (like a level's background from multiple tiles)
/// \li applying post-effects to the whole scene with shaders
/// \li creating a sprite from a 3D object rendered with OpenGL
/// \li etc.
///
/// Usage example:
///
/// \code
/// // Create a new render-window
/// sf::RenderWindow window(sf::VideoMode({800, 600}), "SFML window");
///
/// // Create a new render-texture
/// sf::RenderTexture texture({500, 500});
///
/// // The main loop
/// while (window.isOpen())
/// {
/// // Event processing
/// // ...
///
/// // Clear the whole texture with red color
/// texture.clear(sf::Color::Red);
///
/// // Draw stuff to the texture
/// texture.draw(sprite); // sprite is a sf::Sprite
/// texture.draw(shape); // shape is a sf::Shape
/// texture.draw(text); // text is a sf::Text
///
/// // We're done drawing to the texture
/// texture.display();
///
/// // Now we start rendering to the window, clear it first
/// window.clear();
///
/// // Draw the texture
/// sf::Sprite sprite(texture.getTexture());
/// window.draw(sprite);
///
/// // End the current frame and display its contents on screen
/// window.display();
/// }
/// \endcode
///
/// Like `sf::RenderWindow`, `sf::RenderTexture` is still able to render direct
/// OpenGL stuff. It is even possible to mix together OpenGL calls
/// and regular SFML drawing commands. If you need a depth buffer for
/// 3D rendering, don't forget to request it when calling `RenderTexture::create`.
///
/// \see `sf::RenderTarget`, `sf::RenderWindow`, `sf::View`, `sf::Texture`
///
////////////////////////////////////////////////////////////

View File

@ -1,308 +0,0 @@
////////////////////////////////////////////////////////////
//
// SFML - Simple and Fast Multimedia Library
// Copyright (C) 2007-2025 Laurent Gomila (laurent@sfml-dev.org)
//
// This software is provided 'as-is', without any express or implied warranty.
// In no event will the authors be held liable for any damages arising from the use of this software.
//
// Permission is granted to anyone to use this software for any purpose,
// including commercial applications, and to alter it and redistribute it freely,
// subject to the following restrictions:
//
// 1. The origin of this software must not be misrepresented;
// you must not claim that you wrote the original software.
// If you use this software in a product, an acknowledgment
// in the product documentation would be appreciated but is not required.
//
// 2. Altered source versions must be plainly marked as such,
// and must not be misrepresented as being the original software.
//
// 3. This notice may not be removed or altered from any source distribution.
//
////////////////////////////////////////////////////////////
#pragma once
////////////////////////////////////////////////////////////
// Headers
////////////////////////////////////////////////////////////
#include <SFML/Graphics/Export.hpp>
#include <SFML/Graphics/RenderTarget.hpp>
#include <SFML/Window/ContextSettings.hpp>
#include <SFML/Window/VideoMode.hpp>
#include <SFML/Window/Window.hpp>
#include <SFML/Window/WindowEnums.hpp>
#include <SFML/Window/WindowHandle.hpp>
#include <SFML/System/Vector2.hpp>
#include <cstdint>
namespace sf
{
class Image;
class String;
////////////////////////////////////////////////////////////
/// \brief Window that can serve as a target for 2D drawing
///
////////////////////////////////////////////////////////////
class SFML_GRAPHICS_API RenderWindow : public Window, public RenderTarget
{
public:
////////////////////////////////////////////////////////////
/// \brief Default constructor
///
/// This constructor doesn't actually create the window,
/// use the other constructors or call `create()` to do so.
///
////////////////////////////////////////////////////////////
RenderWindow() = default;
////////////////////////////////////////////////////////////
/// \brief Construct a new window
///
/// This constructor creates the window with the size and pixel
/// depth defined in `mode`. An optional style can be passed to
/// customize the look and behavior of the window (borders,
/// title bar, resizable, closable, ...).
///
/// The last parameter is an optional structure specifying
/// advanced OpenGL context settings such as anti-aliasing,
/// depth-buffer bits, etc. You shouldn't care about these
/// parameters for a regular usage of the graphics module.
///
/// \param mode Video mode to use (defines the width, height and depth of the rendering area of the window)
/// \param title Title of the window
/// \param style %Window style, a bitwise OR combination of `sf::Style` enumerators
/// \param state %Window state
/// \param settings Additional settings for the underlying OpenGL context
///
////////////////////////////////////////////////////////////
RenderWindow(VideoMode mode,
const String& title,
std::uint32_t style = Style::Default,
State state = State::Windowed,
const ContextSettings& settings = {});
////////////////////////////////////////////////////////////
/// \brief Construct a new window
///
/// This constructor creates the window with the size and pixel
/// depth defined in `mode`. If `state` is `State::Fullscreen`,
/// then `mode` must be a valid video mode.
///
/// The last parameter is an optional structure specifying
/// advanced OpenGL context settings such as anti-aliasing,
/// depth-buffer bits, etc.
///
/// \param mode Video mode to use (defines the width, height and depth of the rendering area of the window)
/// \param title Title of the window
/// \param state %Window state
/// \param settings Additional settings for the underlying OpenGL context
///
////////////////////////////////////////////////////////////
RenderWindow(VideoMode mode, const String& title, State state, const ContextSettings& settings = {});
////////////////////////////////////////////////////////////
/// \brief Construct the window from an existing control
///
/// Use this constructor if you want to create an SFML
/// rendering area into an already existing control.
///
/// The second parameter is an optional structure specifying
/// advanced OpenGL context settings such as anti-aliasing,
/// depth-buffer bits, etc. You shouldn't care about these
/// parameters for a regular usage of the graphics module.
///
/// \param handle Platform-specific handle of the control (\a HWND on
/// Windows, \a %Window on Linux/FreeBSD, \a NSWindow on macOS)
/// \param settings Additional settings for the underlying OpenGL context
///
////////////////////////////////////////////////////////////
explicit RenderWindow(WindowHandle handle, const ContextSettings& settings = {});
////////////////////////////////////////////////////////////
/// \brief Get the size of the rendering region of the window
///
/// The size doesn't include the titlebar and borders
/// of the window.
///
/// \return Size in pixels
///
////////////////////////////////////////////////////////////
[[nodiscard]] Vector2u getSize() const override;
////////////////////////////////////////////////////////////
/// \brief Change the window's icon
///
/// The OS default icon is used by default.
///
/// \param icon Image to use as the icon. The image is copied,
/// so you need not keep the source alive after
/// calling this function.
///
////////////////////////////////////////////////////////////
void setIcon(const Image& icon);
using Window::setIcon;
////////////////////////////////////////////////////////////
/// \brief Tell if the window will use sRGB encoding when drawing on it
///
/// You can request sRGB encoding for a window by having the sRgbCapable flag set in the `ContextSettings`
///
/// \return `true` if the window use sRGB encoding, `false` otherwise
///
////////////////////////////////////////////////////////////
[[nodiscard]] bool isSrgb() const override;
////////////////////////////////////////////////////////////
/// \brief Activate or deactivate the window as the current target
/// for OpenGL rendering
///
/// A window is active only on the current thread, if you want to
/// make it active on another thread you have to deactivate it
/// on the previous thread first if it was active.
/// Only one window can be active on a thread at a time, thus
/// the window previously active (if any) automatically gets deactivated.
/// This is not to be confused with `requestFocus()`.
///
/// \param active `true` to activate, `false` to deactivate
///
/// \return `true` if operation was successful, `false` otherwise
///
////////////////////////////////////////////////////////////
[[nodiscard]] bool setActive(bool active = true) override;
protected:
////////////////////////////////////////////////////////////
/// \brief Function called after the window has been created
///
/// This function is called so that derived classes can
/// perform their own specific initialization as soon as
/// the window is created.
///
////////////////////////////////////////////////////////////
void onCreate() override;
////////////////////////////////////////////////////////////
/// \brief Function called after the window has been resized
///
/// This function is called so that derived classes can
/// perform custom actions when the size of the window changes.
///
////////////////////////////////////////////////////////////
void onResize() override;
private:
////////////////////////////////////////////////////////////
// Member data
////////////////////////////////////////////////////////////
unsigned int m_defaultFrameBuffer{}; //!< Framebuffer to bind when targeting this window
};
} // namespace sf
////////////////////////////////////////////////////////////
/// \class sf::RenderWindow
/// \ingroup graphics
///
/// `sf::RenderWindow` is the main class of the Graphics module.
/// It defines an OS window that can be painted using the other
/// classes of the graphics module.
///
/// `sf::RenderWindow` is derived from `sf::Window`, thus it inherits
/// all its features: events, window management, OpenGL rendering,
/// etc. See the documentation of `sf::Window` for a more complete
/// description of all these features, as well as code examples.
///
/// On top of that, `sf::RenderWindow` adds more features related to
/// 2D drawing with the graphics module (see its base class
/// `sf::RenderTarget` for more details).
/// Here is a typical rendering and event loop with a `sf::RenderWindow`:
///
/// \code
/// // Declare and create a new render-window
/// sf::RenderWindow window(sf::VideoMode({800, 600}), "SFML window");
///
/// // Limit the framerate to 60 frames per second (this step is optional)
/// window.setFramerateLimit(60);
///
/// // The main loop - ends as soon as the window is closed
/// while (window.isOpen())
/// {
/// // Event processing
/// while (const std::optional event = window.pollEvent())
/// {
/// // Request for closing the window
/// if (event->is<sf::Event::Closed>())
/// window.close();
/// }
///
/// // Clear the whole window before rendering a new frame
/// window.clear();
///
/// // Draw some graphical entities
/// window.draw(sprite);
/// window.draw(circle);
/// window.draw(text);
///
/// // End the current frame and display its contents on screen
/// window.display();
/// }
/// \endcode
///
/// Like `sf::Window`, `sf::RenderWindow` is still able to render direct
/// OpenGL stuff. It is even possible to mix together OpenGL calls
/// and regular SFML drawing commands.
///
/// \code
/// // Create the render window
/// sf::RenderWindow window(sf::VideoMode({800, 600}), "SFML OpenGL");
///
/// // Create a sprite and a text to display
/// const sf::Texture texture("circle.png");
/// sf::Sprite sprite(texture);
/// const sf::Font font("arial.ttf");
/// sf::Text text(font);
/// ...
///
/// // Perform OpenGL initializations
/// glMatrixMode(GL_PROJECTION);
/// ...
///
/// // Start the rendering loop
/// while (window.isOpen())
/// {
/// // Process events
/// ...
///
/// // Draw a background sprite
/// window.pushGLStates();
/// window.draw(sprite);
/// window.popGLStates();
///
/// // Draw a 3D object using OpenGL
/// glBegin(GL_TRIANGLES);
/// glVertex3f(...);
/// ...
/// glEnd();
///
/// // Draw text on top of the 3D object
/// window.pushGLStates();
/// window.draw(text);
/// window.popGLStates();
///
/// // Finally, display the rendered frame on screen
/// window.display();
/// }
/// \endcode
///
/// \see `sf::Window`, `sf::RenderTarget`, `sf::RenderTexture`, `sf::View`
///
////////////////////////////////////////////////////////////

File diff suppressed because it is too large Load Diff

View File

@ -1,357 +0,0 @@
////////////////////////////////////////////////////////////
//
// SFML - Simple and Fast Multimedia Library
// Copyright (C) 2007-2025 Laurent Gomila (laurent@sfml-dev.org)
//
// This software is provided 'as-is', without any express or implied warranty.
// In no event will the authors be held liable for any damages arising from the use of this software.
//
// Permission is granted to anyone to use this software for any purpose,
// including commercial applications, and to alter it and redistribute it freely,
// subject to the following restrictions:
//
// 1. The origin of this software must not be misrepresented;
// you must not claim that you wrote the original software.
// If you use this software in a product, an acknowledgment
// in the product documentation would be appreciated but is not required.
//
// 2. Altered source versions must be plainly marked as such,
// and must not be misrepresented as being the original software.
//
// 3. This notice may not be removed or altered from any source distribution.
//
////////////////////////////////////////////////////////////
#pragma once
////////////////////////////////////////////////////////////
// Headers
////////////////////////////////////////////////////////////
#include <SFML/Graphics/Export.hpp>
#include <SFML/Graphics/Color.hpp>
#include <SFML/Graphics/Drawable.hpp>
#include <SFML/Graphics/PrimitiveType.hpp>
#include <SFML/Graphics/Rect.hpp>
#include <SFML/Graphics/RenderStates.hpp>
#include <SFML/Graphics/Transformable.hpp>
#include <SFML/Graphics/VertexArray.hpp>
#include <SFML/System/Vector2.hpp>
#include <cstddef>
namespace sf
{
class Texture;
class RenderTarget;
////////////////////////////////////////////////////////////
/// \brief Base class for textured shapes with outline
///
////////////////////////////////////////////////////////////
class SFML_GRAPHICS_API Shape : public Drawable, public Transformable
{
public:
////////////////////////////////////////////////////////////
/// \brief Change the source texture of the shape
///
/// The `texture` argument refers to a texture that must
/// exist as long as the shape uses it. Indeed, the shape
/// doesn't store its own copy of the texture, but rather keeps
/// a pointer to the one that you passed to this function.
/// If the source texture is destroyed and the shape tries to
/// use it, the behavior is undefined.
/// `texture` can be a null pointer to disable texturing.
/// If `resetRect` is `true`, the `TextureRect` property of
/// the shape is automatically adjusted to the size of the new
/// texture. If it is `false`, the texture rect is left unchanged.
///
/// \param texture New texture
/// \param resetRect Should the texture rect be reset to the size of the new texture?
///
/// \see `getTexture`, `setTextureRect`
///
////////////////////////////////////////////////////////////
void setTexture(const Texture* texture, bool resetRect = false);
////////////////////////////////////////////////////////////
/// \brief Set the sub-rectangle of the texture that the shape will display
///
/// The texture rect is useful when you don't want to display
/// the whole texture, but rather a part of it.
/// By default, the texture rect covers the entire texture.
///
/// \param rect Rectangle defining the region of the texture to display
///
/// \see `getTextureRect`, `setTexture`
///
////////////////////////////////////////////////////////////
void setTextureRect(const IntRect& rect);
////////////////////////////////////////////////////////////
/// \brief Set the fill color of the shape
///
/// This color is modulated (multiplied) with the shape's
/// texture if any. It can be used to colorize the shape,
/// or change its global opacity.
/// You can use `sf::Color::Transparent` to make the inside of
/// the shape transparent, and have the outline alone.
/// By default, the shape's fill color is opaque white.
///
/// \param color New color of the shape
///
/// \see `getFillColor`, `setOutlineColor`
///
////////////////////////////////////////////////////////////
void setFillColor(Color color);
////////////////////////////////////////////////////////////
/// \brief Set the outline color of the shape
///
/// By default, the shape's outline color is opaque white.
///
/// \param color New outline color of the shape
///
/// \see `getOutlineColor`, `setFillColor`
///
////////////////////////////////////////////////////////////
void setOutlineColor(Color color);
////////////////////////////////////////////////////////////
/// \brief Set the thickness of the shape's outline
///
/// Note that negative values are allowed (so that the outline
/// expands towards the center of the shape), and using zero
/// disables the outline.
/// By default, the outline thickness is 0.
///
/// \param thickness New outline thickness
///
/// \see `getOutlineThickness`
///
////////////////////////////////////////////////////////////
void setOutlineThickness(float thickness);
////////////////////////////////////////////////////////////
/// \brief Get the source texture of the shape
///
/// If the shape has no source texture, a `nullptr` is returned.
/// The returned pointer is const, which means that you can't
/// modify the texture when you retrieve it with this function.
///
/// \return Pointer to the shape's texture
///
/// \see `setTexture`
///
////////////////////////////////////////////////////////////
[[nodiscard]] const Texture* getTexture() const;
////////////////////////////////////////////////////////////
/// \brief Get the sub-rectangle of the texture displayed by the shape
///
/// \return Texture rectangle of the shape
///
/// \see `setTextureRect`
///
////////////////////////////////////////////////////////////
[[nodiscard]] const IntRect& getTextureRect() const;
////////////////////////////////////////////////////////////
/// \brief Get the fill color of the shape
///
/// \return Fill color of the shape
///
/// \see `setFillColor`
///
////////////////////////////////////////////////////////////
[[nodiscard]] Color getFillColor() const;
////////////////////////////////////////////////////////////
/// \brief Get the outline color of the shape
///
/// \return Outline color of the shape
///
/// \see `setOutlineColor`
///
////////////////////////////////////////////////////////////
[[nodiscard]] Color getOutlineColor() const;
////////////////////////////////////////////////////////////
/// \brief Get the outline thickness of the shape
///
/// \return Outline thickness of the shape
///
/// \see `setOutlineThickness`
///
////////////////////////////////////////////////////////////
[[nodiscard]] float getOutlineThickness() const;
////////////////////////////////////////////////////////////
/// \brief Get the total number of points of the shape
///
/// \return Number of points of the shape
///
/// \see `getPoint`
///
////////////////////////////////////////////////////////////
[[nodiscard]] virtual std::size_t getPointCount() const = 0;
////////////////////////////////////////////////////////////
/// \brief Get a point of the shape
///
/// The returned point is in local coordinates, that is,
/// the shape's transforms (position, rotation, scale) are
/// not taken into account.
/// The result is undefined if `index` is out of the valid range.
///
/// \param index Index of the point to get, in range [0 .. getPointCount() - 1]
///
/// \return `index`-th point of the shape
///
/// \see `getPointCount`
///
////////////////////////////////////////////////////////////
[[nodiscard]] virtual Vector2f getPoint(std::size_t index) const = 0;
////////////////////////////////////////////////////////////
/// \brief Get the geometric center of the shape
///
/// The returned point is in local coordinates, that is,
/// the shape's transforms (position, rotation, scale) are
/// not taken into account.
///
/// \return The geometric center of the shape
///
////////////////////////////////////////////////////////////
[[nodiscard]] virtual Vector2f getGeometricCenter() const;
////////////////////////////////////////////////////////////
/// \brief Get the local bounding rectangle of the entity
///
/// The returned rectangle is in local coordinates, which means
/// that it ignores the transformations (translation, rotation,
/// scale, ...) that are applied to the entity.
/// In other words, this function returns the bounds of the
/// entity in the entity's coordinate system.
///
/// \return Local bounding rectangle of the entity
///
////////////////////////////////////////////////////////////
[[nodiscard]] FloatRect getLocalBounds() const;
////////////////////////////////////////////////////////////
/// \brief Get the global (non-minimal) bounding rectangle of the entity
///
/// The returned rectangle is in global coordinates, which means
/// that it takes into account the transformations (translation,
/// rotation, scale, ...) that are applied to the entity.
/// In other words, this function returns the bounds of the
/// shape in the global 2D world's coordinate system.
///
/// This function does not necessarily return the _minimal_
/// bounding rectangle. It merely ensures that the returned
/// rectangle covers all the vertices (but possibly more).
/// This allows for a fast approximation of the bounds as a
/// first check; you may want to use more precise checks
/// on top of that.
///
/// \return Global bounding rectangle of the entity
///
////////////////////////////////////////////////////////////
[[nodiscard]] FloatRect getGlobalBounds() const;
protected:
////////////////////////////////////////////////////////////
/// \brief Recompute the internal geometry of the shape
///
/// This function must be called by the derived class every time
/// the shape's points change (i.e. the result of either
/// getPointCount or getPoint is different).
///
////////////////////////////////////////////////////////////
void update();
private:
////////////////////////////////////////////////////////////
/// \brief Draw the shape to a render target
///
/// \param target Render target to draw to
/// \param states Current render states
///
////////////////////////////////////////////////////////////
void draw(RenderTarget& target, RenderStates states) const override;
////////////////////////////////////////////////////////////
/// \brief Update the fill vertices' color
///
////////////////////////////////////////////////////////////
void updateFillColors();
////////////////////////////////////////////////////////////
/// \brief Update the fill vertices' texture coordinates
///
////////////////////////////////////////////////////////////
void updateTexCoords();
////////////////////////////////////////////////////////////
/// \brief Update the outline vertices' position
///
////////////////////////////////////////////////////////////
void updateOutline();
////////////////////////////////////////////////////////////
/// \brief Update the outline vertices' color
///
////////////////////////////////////////////////////////////
void updateOutlineColors();
////////////////////////////////////////////////////////////
// Member data
////////////////////////////////////////////////////////////
const Texture* m_texture{}; //!< Texture of the shape
IntRect m_textureRect; //!< Rectangle defining the area of the source texture to display
Color m_fillColor{Color::White}; //!< Fill color
Color m_outlineColor{Color::White}; //!< Outline color
float m_outlineThickness{}; //!< Thickness of the shape's outline
VertexArray m_vertices{PrimitiveType::TriangleFan}; //!< Vertex array containing the fill geometry
VertexArray m_outlineVertices{PrimitiveType::TriangleStrip}; //!< Vertex array containing the outline geometry
FloatRect m_insideBounds; //!< Bounding rectangle of the inside (fill)
FloatRect m_bounds; //!< Bounding rectangle of the whole shape (outline + fill)
};
} // namespace sf
////////////////////////////////////////////////////////////
/// \class sf::Shape
/// \ingroup graphics
///
/// `sf::Shape` is a drawable class that allows to define and
/// display a custom convex shape on a render target.
/// It's only an abstract base, it needs to be specialized for
/// concrete types of shapes (circle, rectangle, convex polygon,
/// star, ...).
///
/// In addition to the attributes provided by the specialized
/// shape classes, a shape always has the following attributes:
/// \li a texture
/// \li a texture rectangle
/// \li a fill color
/// \li an outline color
/// \li an outline thickness
///
/// Each feature is optional, and can be disabled easily:
/// \li the texture can be null
/// \li the fill/outline colors can be `sf::Color::Transparent`
/// \li the outline thickness can be zero
///
/// You can write your own derived shape class, there are only
/// two virtual functions to override:
/// \li getPointCount must return the number of points of the shape
/// \li getPoint must return the points of the shape
///
/// \see `sf::RectangleShape`, `sf::CircleShape`, `sf::ConvexShape`, `sf::Transformable`
///
////////////////////////////////////////////////////////////

View File

@ -1,278 +0,0 @@
////////////////////////////////////////////////////////////
//
// SFML - Simple and Fast Multimedia Library
// Copyright (C) 2007-2025 Laurent Gomila (laurent@sfml-dev.org)
//
// This software is provided 'as-is', without any express or implied warranty.
// In no event will the authors be held liable for any damages arising from the use of this software.
//
// Permission is granted to anyone to use this software for any purpose,
// including commercial applications, and to alter it and redistribute it freely,
// subject to the following restrictions:
//
// 1. The origin of this software must not be misrepresented;
// you must not claim that you wrote the original software.
// If you use this software in a product, an acknowledgment
// in the product documentation would be appreciated but is not required.
//
// 2. Altered source versions must be plainly marked as such,
// and must not be misrepresented as being the original software.
//
// 3. This notice may not be removed or altered from any source distribution.
//
////////////////////////////////////////////////////////////
#pragma once
////////////////////////////////////////////////////////////
// Headers
////////////////////////////////////////////////////////////
#include <SFML/Graphics/Export.hpp>
#include <SFML/Graphics/Drawable.hpp>
#include <SFML/Graphics/Rect.hpp>
#include <SFML/Graphics/RenderStates.hpp>
#include <SFML/Graphics/Transformable.hpp>
#include <SFML/Graphics/Vertex.hpp>
#include <array>
namespace sf
{
class Texture;
////////////////////////////////////////////////////////////
/// \brief Drawable representation of a texture, with its
/// own transformations, color, etc.
///
////////////////////////////////////////////////////////////
class SFML_GRAPHICS_API Sprite : public Drawable, public Transformable
{
public:
////////////////////////////////////////////////////////////
/// \brief Construct the sprite from a source texture
///
/// \param texture Source texture
///
/// \see `setTexture`
///
////////////////////////////////////////////////////////////
explicit Sprite(const Texture& texture);
////////////////////////////////////////////////////////////
/// \brief Disallow construction from a temporary texture
///
////////////////////////////////////////////////////////////
explicit Sprite(const Texture&& texture) = delete;
////////////////////////////////////////////////////////////
/// \brief Construct the sprite from a sub-rectangle of a source texture
///
/// \param texture Source texture
/// \param rectangle Sub-rectangle of the texture to assign to the sprite
///
/// \see `setTexture`, `setTextureRect`
///
////////////////////////////////////////////////////////////
Sprite(const Texture& texture, const IntRect& rectangle);
////////////////////////////////////////////////////////////
/// \brief Disallow construction from a temporary texture
///
////////////////////////////////////////////////////////////
Sprite(const Texture&& texture, const IntRect& rectangle) = delete;
////////////////////////////////////////////////////////////
/// \brief Change the source texture of the sprite
///
/// The `texture` argument refers to a texture that must
/// exist as long as the sprite uses it. Indeed, the sprite
/// doesn't store its own copy of the texture, but rather keeps
/// a pointer to the one that you passed to this function.
/// If the source texture is destroyed and the sprite tries to
/// use it, the behavior is undefined.
/// If `resetRect` is `true`, the `TextureRect` property of
/// the sprite is automatically adjusted to the size of the new
/// texture. If it is `false`, the texture rect is left unchanged.
///
/// \param texture New texture
/// \param resetRect Should the texture rect be reset to the size of the new texture?
///
/// \see `getTexture`, `setTextureRect`
///
////////////////////////////////////////////////////////////
void setTexture(const Texture& texture, bool resetRect = false);
////////////////////////////////////////////////////////////
/// \brief Disallow setting from a temporary texture
///
////////////////////////////////////////////////////////////
void setTexture(const Texture&& texture, bool resetRect = false) = delete;
////////////////////////////////////////////////////////////
/// \brief Set the sub-rectangle of the texture that the sprite will display
///
/// The texture rect is useful when you don't want to display
/// the whole texture, but rather a part of it.
/// By default, the texture rect covers the entire texture.
///
/// \param rectangle Rectangle defining the region of the texture to display
///
/// \see `getTextureRect`, `setTexture`
///
////////////////////////////////////////////////////////////
void setTextureRect(const IntRect& rectangle);
////////////////////////////////////////////////////////////
/// \brief Set the global color of the sprite
///
/// This color is modulated (multiplied) with the sprite's
/// texture. It can be used to colorize the sprite, or change
/// its global opacity.
/// By default, the sprite's color is opaque white.
///
/// \param color New color of the sprite
///
/// \see `getColor`
///
////////////////////////////////////////////////////////////
void setColor(Color color);
////////////////////////////////////////////////////////////
/// \brief Get the source texture of the sprite
///
/// The returned reference is const, which means that you can't
/// modify the texture when you retrieve it with this function.
///
/// \return Reference to the sprite's texture
///
/// \see `setTexture`
///
////////////////////////////////////////////////////////////
[[nodiscard]] const Texture& getTexture() const;
////////////////////////////////////////////////////////////
/// \brief Get the sub-rectangle of the texture displayed by the sprite
///
/// \return Texture rectangle of the sprite
///
/// \see `setTextureRect`
///
////////////////////////////////////////////////////////////
[[nodiscard]] const IntRect& getTextureRect() const;
////////////////////////////////////////////////////////////
/// \brief Get the global color of the sprite
///
/// \return Global color of the sprite
///
/// \see `setColor`
///
////////////////////////////////////////////////////////////
[[nodiscard]] Color getColor() const;
////////////////////////////////////////////////////////////
/// \brief Get the local bounding rectangle of the entity
///
/// The returned rectangle is in local coordinates, which means
/// that it ignores the transformations (translation, rotation,
/// scale, ...) that are applied to the entity.
/// In other words, this function returns the bounds of the
/// entity in the entity's coordinate system.
///
/// \return Local bounding rectangle of the entity
///
////////////////////////////////////////////////////////////
[[nodiscard]] FloatRect getLocalBounds() const;
////////////////////////////////////////////////////////////
/// \brief Get the global bounding rectangle of the entity
///
/// The returned rectangle is in global coordinates, which means
/// that it takes into account the transformations (translation,
/// rotation, scale, ...) that are applied to the entity.
/// In other words, this function returns the bounds of the
/// sprite in the global 2D world's coordinate system.
///
/// \return Global bounding rectangle of the entity
///
////////////////////////////////////////////////////////////
[[nodiscard]] FloatRect getGlobalBounds() const;
private:
////////////////////////////////////////////////////////////
/// \brief Draw the sprite to a render target
///
/// \param target Render target to draw to
/// \param states Current render states
///
////////////////////////////////////////////////////////////
void draw(RenderTarget& target, RenderStates states) const override;
////////////////////////////////////////////////////////////
/// \brief Update the vertices' positions and texture coordinates
///
////////////////////////////////////////////////////////////
void updateVertices();
////////////////////////////////////////////////////////////
// Member data
////////////////////////////////////////////////////////////
std::array<Vertex, 4> m_vertices; //!< Vertices defining the sprite's geometry
const Texture* m_texture; //!< Texture of the sprite
IntRect m_textureRect; //!< Rectangle defining the area of the source texture to display
};
} // namespace sf
////////////////////////////////////////////////////////////
/// \class sf::Sprite
/// \ingroup graphics
///
/// `sf::Sprite` is a drawable class that allows to easily display
/// a texture (or a part of it) on a render target.
///
/// It inherits all the functions from `sf::Transformable`:
/// position, rotation, scale, origin. It also adds sprite-specific
/// properties such as the texture to use, the part of it to display,
/// and some convenience functions to change the overall color of the
/// sprite, or to get its bounding rectangle.
///
/// `sf::Sprite` works in combination with the `sf::Texture` class, which
/// loads and provides the pixel data of a given texture.
///
/// The separation of `sf::Sprite` and `sf::Texture` allows more flexibility
/// and better performances: indeed a `sf::Texture` is a heavy resource,
/// and any operation on it is slow (often too slow for real-time
/// applications). On the other side, a `sf::Sprite` is a lightweight
/// object which can use the pixel data of a `sf::Texture` and draw
/// it with its own transformation/color/blending attributes.
///
/// It is important to note that the `sf::Sprite` instance doesn't
/// copy the texture that it uses, it only keeps a reference to it.
/// Thus, a `sf::Texture` must not be destroyed while it is
/// used by a `sf::Sprite` (i.e. never write a function that
/// uses a local `sf::Texture` instance for creating a sprite).
///
/// See also the note on coordinates and undistorted rendering in `sf::Transformable`.
///
/// Usage example:
/// \code
/// // Load a texture
/// const sf::Texture texture("texture.png");
///
/// // Create a sprite
/// sf::Sprite sprite(texture);
/// sprite.setTextureRect({{10, 10}, {50, 30}});
/// sprite.setColor({255, 255, 255, 200});
/// sprite.setPosition({100.f, 25.f});
///
/// // Draw it
/// window.draw(sprite);
/// \endcode
///
/// \see `sf::Texture`, `sf::Transformable`
///
////////////////////////////////////////////////////////////

View File

@ -1,256 +0,0 @@
////////////////////////////////////////////////////////////
//
// SFML - Simple and Fast Multimedia Library
// Copyright (C) 2007-2025 Laurent Gomila (laurent@sfml-dev.org)
//
// This software is provided 'as-is', without any express or implied warranty.
// In no event will the authors be held liable for any damages arising from the use of this software.
//
// Permission is granted to anyone to use this software for any purpose,
// including commercial applications, and to alter it and redistribute it freely,
// subject to the following restrictions:
//
// 1. The origin of this software must not be misrepresented;
// you must not claim that you wrote the original software.
// If you use this software in a product, an acknowledgment
// in the product documentation would be appreciated but is not required.
//
// 2. Altered source versions must be plainly marked as such,
// and must not be misrepresented as being the original software.
//
// 3. This notice may not be removed or altered from any source distribution.
//
////////////////////////////////////////////////////////////
#pragma once
////////////////////////////////////////////////////////////
// Headers
////////////////////////////////////////////////////////////
#include <SFML/Graphics/Export.hpp>
namespace sf
{
////////////////////////////////////////////////////////
/// \brief Enumeration of the stencil test comparisons that can be performed
///
/// The comparisons are mapped directly to their OpenGL equivalents,
/// specified by `glStencilFunc()`.
////////////////////////////////////////////////////////
enum class StencilComparison
{
Never, //!< The stencil test never passes
Less, //!< The stencil test passes if the new value is less than the value in the stencil buffer
LessEqual, //!< The stencil test passes if the new value is less than or equal to the value in the stencil buffer
Greater, //!< The stencil test passes if the new value is greater than the value in the stencil buffer
GreaterEqual, //!< The stencil test passes if the new value is greater than or equal to the value in the stencil buffer
Equal, //!< The stencil test passes if the new value is strictly equal to the value in the stencil buffer
NotEqual, //!< The stencil test passes if the new value is strictly unequal to the value in the stencil buffer
Always //!< The stencil test always passes
};
////////////////////////////////////////////////////////
/// \brief Enumeration of the stencil buffer update operations
///
/// The update operations are mapped directly to their OpenGL equivalents,
/// specified by `glStencilOp()`.
////////////////////////////////////////////////////////
enum class StencilUpdateOperation
{
Keep, //!< If the stencil test passes, the value in the stencil buffer is not modified
Zero, //!< If the stencil test passes, the value in the stencil buffer is set to zero
Replace, //!< If the stencil test passes, the value in the stencil buffer is set to the new value
Increment, //!< If the stencil test passes, the value in the stencil buffer is incremented and if required clamped
Decrement, //!< If the stencil test passes, the value in the stencil buffer is decremented and if required clamped
Invert, //!< If the stencil test passes, the value in the stencil buffer is bitwise inverted
};
////////////////////////////////////////////////////////
/// \brief Stencil value type (also used as a mask)
///
////////////////////////////////////////////////////////
struct SFML_GRAPHICS_API StencilValue
{
////////////////////////////////////////////////////////////
/// \brief Construct a stencil value from a signed integer
///
/// \param theValue Signed integer value to use
///
////////////////////////////////////////////////////////////
StencilValue(int theValue);
////////////////////////////////////////////////////////////
/// \brief Construct a stencil value from an unsigned integer
///
/// \param theValue Unsigned integer value to use
///
////////////////////////////////////////////////////////////
StencilValue(unsigned int theValue);
////////////////////////////////////////////////////////////
/// \brief Disable construction from any other type
///
////////////////////////////////////////////////////////////
template <typename T>
StencilValue(T) = delete;
unsigned int value{}; //!< The stored stencil value
};
////////////////////////////////////////////////////////////
/// \brief Stencil modes for drawing
///
////////////////////////////////////////////////////////////
struct SFML_GRAPHICS_API StencilMode
{
StencilComparison stencilComparison{StencilComparison::Always}; //!< The comparison we're performing the stencil test with
StencilUpdateOperation stencilUpdateOperation{
StencilUpdateOperation::Keep}; //!< The update operation to perform if the stencil test passes
StencilValue stencilReference{0}; //!< The reference value we're performing the stencil test with
StencilValue stencilMask{~0u}; //!< The mask to apply to both the reference value and the value in the stencil buffer
bool stencilOnly{}; //!< Whether we should update the color buffer in addition to the stencil buffer
};
////////////////////////////////////////////////////////////
/// \relates StencilMode
/// \brief Overload of the `operator==`
///
/// \param left Left operand
/// \param right Right operand
///
/// \return `true` if stencil modes are equal, `false` if they are different
///
////////////////////////////////////////////////////////////
[[nodiscard]] SFML_GRAPHICS_API bool operator==(const StencilMode& left, const StencilMode& right);
////////////////////////////////////////////////////////////
/// \relates StencilMode
/// \brief Overload of the `operator!=`
///
/// \param left Left operand
/// \param right Right operand
///
/// \return `true` if stencil modes are different, `false` if they are equal
///
////////////////////////////////////////////////////////////
[[nodiscard]] SFML_GRAPHICS_API bool operator!=(const StencilMode& left, const StencilMode& right);
} // namespace sf
////////////////////////////////////////////////////////////
/// \class sf::StencilMode
/// \ingroup graphics
///
/// `sf::StencilMode` is a class that controls stencil testing.
///
/// In addition to drawing to the visible portion of a render target,
/// there is the possibility to "draw" to a so-called stencil buffer.
/// The stencil buffer is a special non-visible buffer that can contain
/// a single value per pixel that is drawn. This can be thought of as a
/// fifth value in addition to red, green, blue and alpha values. The maximum
/// value that can be represented depends on what is supported by the system.
/// Typically support for a 8-bit stencil buffer should always be available.
/// This will also have to be requested when creating a render target via
/// the `sf::ContextSettings` that is passed during creation. Stencil testing
/// will not work if there is no stencil buffer available in the target
/// that is being drawn to.
///
/// Initially, just like with the visible color buffer, the stencil value of
/// each pixel is set to an undefined value. Calling `sf::RenderTarget::clear`
/// will set each pixel's stencil value to 0. `sf::RenderTarget::clear` can be
/// called at any time to reset the stencil values back to 0.
///
/// When drawing an object, before each pixel of the color buffer is updated
/// with its new color value, the stencil test is performed. During this test
/// 2 values are compared with each other: the reference value that is passed
/// via `sf::StencilMode` and the value that is currently in the stencil buffer.
/// The arithmetic comparison that is performed on the 2 values can also be
/// controlled via `sf::StencilMode`. Depending on whether the test passes i.e.
/// the comparison yields `true`, the color buffer is updated with its new RGBA
/// value and if set in `sf::StencilMode` the stencil buffer is updated
/// accordingly. The new stencil value will be used during stencil testing the
/// next time the pixel is drawn to.
///
/// The class is composed of 5 components, each of which has its
/// own public member variable:
/// \li Stencil Comparison (\ref stencilComparison)
/// \li Stencil Update Operation (\ref stencilUpdateOperation)
/// \li Stencil Reference Value (\ref stencilReference)
/// \li Stencil Mask Value (\ref stencilMask)
/// \li Stencil Only Update (\ref stencilOnly)
///
/// The stencil comparison specifies the comparison that is performed between
/// the reference value of the currently active `sf::StencilMode` and the value
/// that is currently in the stencil buffer. This comparison determines whether
/// the stencil test passes or fails.
///
/// The stencil update operation specifies how the stencil buffer is updated if
/// the stencil test passes. If the stencil test fails, neither the color or
/// stencil buffers will be modified. If incrementing or decrementing the
/// stencil value, the new value will be clamped to the range from 0 to the
/// maximum representable value given the bit width of the stencil buffer
/// e.g. 255 if an 8-bit stencil buffer is being used.
///
/// The reference value is used both during the comparison with the current
/// stencil buffer value and as the new value to be written when the operation
/// is set to Replace.
///
/// The mask value is used to mask the bits of both the reference value and
/// the value in the stencil buffer during the comparison and when updating.
/// The mask can be used to e.g. segment the stencil value bits into separate
/// regions that are used for different purposes.
///
/// In certain situations, it might make sense to only write to the stencil
/// buffer and not the color buffer during a draw. The written stencil buffer
/// value can then be used in subsequent draws as a masking region.
///
/// In SFML, a stencil mode can be specified every time you draw a `sf::Drawable`
/// object to a render target. It is part of the `sf::RenderStates` compound
/// that is passed to the member function `sf::RenderTarget::draw()`.
///
/// Usage example:
/// \code
/// // Make sure we create a RenderTarget with a stencil buffer by specifying it via the context settings
/// sf::RenderWindow window(sf::VideoMode({250, 200}), "Stencil Window", sf::Style::Default, sf::ContextSettings{0, 8});
///
/// ...
///
/// // Left circle
/// sf::CircleShape left(100.f);
/// left.setFillColor(sf::Color::Green);
/// left.setPosition({0, 0});
///
/// // Middle circle
/// sf::CircleShape middle(100.f);
/// middle.setFillColor(sf::Color::Yellow);
/// middle.setPosition({25, 0});
///
/// // Right circle
/// sf::CircleShape right(100.f);
/// right.setFillColor(sf::Color::Red);
/// right.setPosition({50, 0});
///
/// ...
///
/// // Clear the stencil buffer to 0 at the start of every frame
/// window.clear(sf::Color::Black, 0);
///
/// ...
///
/// // Draw the middle circle in a stencil-only pass and write the value 1
/// // to the stencil buffer for every pixel the circle would have affected
/// window.draw(middle, sf::StencilMode{sf::StencilComparison::Always, sf::StencilUpdateOperation::Replace, 1, 0xFF, true});
///
/// // Draw the left and right circles
/// // Only allow rendering to pixels whose stencil value is not
/// // equal to 1 i.e. weren't written when drawing the middle circle
/// window.draw(left, sf::StencilMode{sf::StencilComparison::NotEqual, sf::StencilUpdateOperation::Keep, 1, 0xFF, false});
/// window.draw(right, sf::StencilMode{sf::StencilComparison::NotEqual, sf::StencilUpdateOperation::Keep, 1, 0xFF, false});
/// \endcode
///
/// \see `sf::RenderStates`, `sf::RenderTarget`
///
////////////////////////////////////////////////////////////

View File

@ -1,486 +0,0 @@
////////////////////////////////////////////////////////////
//
// SFML - Simple and Fast Multimedia Library
// Copyright (C) 2007-2025 Laurent Gomila (laurent@sfml-dev.org)
//
// This software is provided 'as-is', without any express or implied warranty.
// In no event will the authors be held liable for any damages arising from the use of this software.
//
// Permission is granted to anyone to use this software for any purpose,
// including commercial applications, and to alter it and redistribute it freely,
// subject to the following restrictions:
//
// 1. The origin of this software must not be misrepresented;
// you must not claim that you wrote the original software.
// If you use this software in a product, an acknowledgment
// in the product documentation would be appreciated but is not required.
//
// 2. Altered source versions must be plainly marked as such,
// and must not be misrepresented as being the original software.
//
// 3. This notice may not be removed or altered from any source distribution.
//
////////////////////////////////////////////////////////////
#pragma once
////////////////////////////////////////////////////////////
// Headers
////////////////////////////////////////////////////////////
#include <SFML/Graphics/Export.hpp>
#include <SFML/Graphics/Color.hpp>
#include <SFML/Graphics/Drawable.hpp>
#include <SFML/Graphics/PrimitiveType.hpp>
#include <SFML/Graphics/Rect.hpp>
#include <SFML/Graphics/RenderStates.hpp>
#include <SFML/Graphics/Transformable.hpp>
#include <SFML/Graphics/VertexArray.hpp>
#include <SFML/System/String.hpp>
#include <SFML/System/Vector2.hpp>
#include <cstddef>
#include <cstdint>
namespace sf
{
class Font;
class RenderTarget;
////////////////////////////////////////////////////////////
/// \brief Graphical text that can be drawn to a render target
///
////////////////////////////////////////////////////////////
class SFML_GRAPHICS_API Text : public Drawable, public Transformable
{
public:
////////////////////////////////////////////////////////////
/// \brief Enumeration of the string drawing styles
///
////////////////////////////////////////////////////////////
enum Style
{
Regular = 0, //!< Regular characters, no style
Bold = 1 << 0, //!< Bold characters
Italic = 1 << 1, //!< Italic characters
Underlined = 1 << 2, //!< Underlined characters
StrikeThrough = 1 << 3 //!< Strike through characters
};
////////////////////////////////////////////////////////////
/// \brief Construct the text from a string, font and size
///
/// Note that if the used font is a bitmap font, it is not
/// scalable, thus not all requested sizes will be available
/// to use. This needs to be taken into consideration when
/// setting the character size. If you need to display text
/// of a certain size, make sure the corresponding bitmap
/// font that supports that size is used.
///
/// \param string Text assigned to the string
/// \param font Font used to draw the string
/// \param characterSize Base size of characters, in pixels
///
////////////////////////////////////////////////////////////
Text(const Font& font, String string = "", unsigned int characterSize = 30);
////////////////////////////////////////////////////////////
/// \brief Disallow construction from a temporary font
///
////////////////////////////////////////////////////////////
Text(const Font&& font, String string = "", unsigned int characterSize = 30) = delete;
////////////////////////////////////////////////////////////
/// \brief Set the text's string
///
/// The `string` argument is a `sf::String`, which can
/// automatically be constructed from standard string types.
/// So, the following calls are all valid:
/// \code
/// text.setString("hello");
/// text.setString(L"hello");
/// text.setString(std::string("hello"));
/// text.setString(std::wstring(L"hello"));
/// \endcode
/// A text's string is empty by default.
///
/// \param string New string
///
/// \see `getString`
///
////////////////////////////////////////////////////////////
void setString(const String& string);
////////////////////////////////////////////////////////////
/// \brief Set the text's font
///
/// The `font` argument refers to a font that must
/// exist as long as the text uses it. Indeed, the text
/// doesn't store its own copy of the font, but rather keeps
/// a pointer to the one that you passed to this function.
/// If the font is destroyed and the text tries to
/// use it, the behavior is undefined.
///
/// \param font New font
///
/// \see `getFont`
///
////////////////////////////////////////////////////////////
void setFont(const Font& font);
////////////////////////////////////////////////////////////
/// \brief Disallow setting from a temporary font
///
////////////////////////////////////////////////////////////
void setFont(const Font&& font) = delete;
////////////////////////////////////////////////////////////
/// \brief Set the character size
///
/// The default size is 30.
///
/// Note that if the used font is a bitmap font, it is not
/// scalable, thus not all requested sizes will be available
/// to use. This needs to be taken into consideration when
/// setting the character size. If you need to display text
/// of a certain size, make sure the corresponding bitmap
/// font that supports that size is used.
///
/// \param size New character size, in pixels
///
/// \see `getCharacterSize`
///
////////////////////////////////////////////////////////////
void setCharacterSize(unsigned int size);
////////////////////////////////////////////////////////////
/// \brief Set the line spacing factor
///
/// The default spacing between lines is defined by the font.
/// This method enables you to set a factor for the spacing
/// between lines. By default the line spacing factor is 1.
///
/// \param spacingFactor New line spacing factor
///
/// \see `getLineSpacing`
///
////////////////////////////////////////////////////////////
void setLineSpacing(float spacingFactor);
////////////////////////////////////////////////////////////
/// \brief Set the letter spacing factor
///
/// The default spacing between letters is defined by the font.
/// This factor doesn't directly apply to the existing
/// spacing between each character, it rather adds a fixed
/// space between them which is calculated from the font
/// metrics and the character size.
/// Note that factors below 1 (including negative numbers) bring
/// characters closer to each other.
/// By default the letter spacing factor is 1.
///
/// \param spacingFactor New letter spacing factor
///
/// \see `getLetterSpacing`
///
////////////////////////////////////////////////////////////
void setLetterSpacing(float spacingFactor);
////////////////////////////////////////////////////////////
/// \brief Set the text's style
///
/// You can pass a combination of one or more styles, for
/// example `sf::Text::Bold | sf::Text::Italic`.
/// The default style is `sf::Text::Regular`.
///
/// \param style New style
///
/// \see `getStyle`
///
////////////////////////////////////////////////////////////
void setStyle(std::uint32_t style);
////////////////////////////////////////////////////////////
/// \brief Set the fill color of the text
///
/// By default, the text's fill color is opaque white.
/// Setting the fill color to a transparent color with an outline
/// will cause the outline to be displayed in the fill area of the text.
///
/// \param color New fill color of the text
///
/// \see `getFillColor`
///
////////////////////////////////////////////////////////////
void setFillColor(Color color);
////////////////////////////////////////////////////////////
/// \brief Set the outline color of the text
///
/// By default, the text's outline color is opaque black.
///
/// \param color New outline color of the text
///
/// \see `getOutlineColor`
///
////////////////////////////////////////////////////////////
void setOutlineColor(Color color);
////////////////////////////////////////////////////////////
/// \brief Set the thickness of the text's outline
///
/// By default, the outline thickness is 0.
///
/// Be aware that using a negative value for the outline
/// thickness will cause distorted rendering.
///
/// \param thickness New outline thickness, in pixels
///
/// \see `getOutlineThickness`
///
////////////////////////////////////////////////////////////
void setOutlineThickness(float thickness);
////////////////////////////////////////////////////////////
/// \brief Get the text's string
///
/// The returned string is a `sf::String`, which can automatically
/// be converted to standard string types. So, the following
/// lines of code are all valid:
/// \code
/// sf::String s1 = text.getString();
/// std::string s2 = text.getString();
/// std::wstring s3 = text.getString();
/// \endcode
///
/// \return Text's string
///
/// \see `setString`
///
////////////////////////////////////////////////////////////
[[nodiscard]] const String& getString() const;
////////////////////////////////////////////////////////////
/// \brief Get the text's font
///
/// The returned reference is const, which means that you
/// cannot modify the font when you get it from this function.
///
/// \return Reference to the text's font
///
/// \see `setFont`
///
////////////////////////////////////////////////////////////
[[nodiscard]] const Font& getFont() const;
////////////////////////////////////////////////////////////
/// \brief Get the character size
///
/// \return Size of the characters, in pixels
///
/// \see `setCharacterSize`
///
////////////////////////////////////////////////////////////
[[nodiscard]] unsigned int getCharacterSize() const;
////////////////////////////////////////////////////////////
/// \brief Get the size of the letter spacing factor
///
/// \return Size of the letter spacing factor
///
/// \see `setLetterSpacing`
///
////////////////////////////////////////////////////////////
[[nodiscard]] float getLetterSpacing() const;
////////////////////////////////////////////////////////////
/// \brief Get the size of the line spacing factor
///
/// \return Size of the line spacing factor
///
/// \see `setLineSpacing`
///
////////////////////////////////////////////////////////////
[[nodiscard]] float getLineSpacing() const;
////////////////////////////////////////////////////////////
/// \brief Get the text's style
///
/// \return Text's style
///
/// \see `setStyle`
///
////////////////////////////////////////////////////////////
[[nodiscard]] std::uint32_t getStyle() const;
////////////////////////////////////////////////////////////
/// \brief Get the fill color of the text
///
/// \return Fill color of the text
///
/// \see `setFillColor`
///
////////////////////////////////////////////////////////////
[[nodiscard]] Color getFillColor() const;
////////////////////////////////////////////////////////////
/// \brief Get the outline color of the text
///
/// \return Outline color of the text
///
/// \see `setOutlineColor`
///
////////////////////////////////////////////////////////////
[[nodiscard]] Color getOutlineColor() const;
////////////////////////////////////////////////////////////
/// \brief Get the outline thickness of the text
///
/// \return Outline thickness of the text, in pixels
///
/// \see `setOutlineThickness`
///
////////////////////////////////////////////////////////////
[[nodiscard]] float getOutlineThickness() const;
////////////////////////////////////////////////////////////
/// \brief Return the position of the `index`-th character
///
/// This function computes the visual position of a character
/// from its index in the string. The returned position is
/// in global coordinates (translation, rotation, scale and
/// origin are applied).
/// If `index` is out of range, the position of the end of
/// the string is returned.
///
/// \param index Index of the character
///
/// \return Position of the character
///
////////////////////////////////////////////////////////////
[[nodiscard]] Vector2f findCharacterPos(std::size_t index) const;
////////////////////////////////////////////////////////////
/// \brief Get the local bounding rectangle of the entity
///
/// The returned rectangle is in local coordinates, which means
/// that it ignores the transformations (translation, rotation,
/// scale, ...) that are applied to the entity.
/// In other words, this function returns the bounds of the
/// entity in the entity's coordinate system.
///
/// \return Local bounding rectangle of the entity
///
////////////////////////////////////////////////////////////
[[nodiscard]] FloatRect getLocalBounds() const;
////////////////////////////////////////////////////////////
/// \brief Get the global bounding rectangle of the entity
///
/// The returned rectangle is in global coordinates, which means
/// that it takes into account the transformations (translation,
/// rotation, scale, ...) that are applied to the entity.
/// In other words, this function returns the bounds of the
/// text in the global 2D world's coordinate system.
///
/// \return Global bounding rectangle of the entity
///
////////////////////////////////////////////////////////////
[[nodiscard]] FloatRect getGlobalBounds() const;
private:
////////////////////////////////////////////////////////////
/// \brief Draw the text to a render target
///
/// \param target Render target to draw to
/// \param states Current render states
///
////////////////////////////////////////////////////////////
void draw(RenderTarget& target, RenderStates states) const override;
////////////////////////////////////////////////////////////
/// \brief Make sure the text's geometry is updated
///
/// All the attributes related to rendering are cached, such
/// that the geometry is only updated when necessary.
///
////////////////////////////////////////////////////////////
void ensureGeometryUpdate() const;
////////////////////////////////////////////////////////////
// Member data
////////////////////////////////////////////////////////////
String m_string; //!< String to display
const Font* m_font{}; //!< Font used to display the string
unsigned int m_characterSize{30}; //!< Base size of characters, in pixels
float m_letterSpacingFactor{1.f}; //!< Spacing factor between letters
float m_lineSpacingFactor{1.f}; //!< Spacing factor between lines
std::uint32_t m_style{Regular}; //!< Text style (see Style enum)
Color m_fillColor{Color::White}; //!< Text fill color
Color m_outlineColor{Color::Black}; //!< Text outline color
float m_outlineThickness{0.f}; //!< Thickness of the text's outline
mutable VertexArray m_vertices{PrimitiveType::Triangles}; //!< Vertex array containing the fill geometry
mutable VertexArray m_outlineVertices{PrimitiveType::Triangles}; //!< Vertex array containing the outline geometry
mutable FloatRect m_bounds; //!< Bounding rectangle of the text (in local coordinates)
mutable bool m_geometryNeedUpdate{}; //!< Does the geometry need to be recomputed?
mutable std::uint64_t m_fontTextureId{}; //!< The font texture id
};
} // namespace sf
////////////////////////////////////////////////////////////
/// \class sf::Text
/// \ingroup graphics
///
/// `sf::Text` is a drawable class that allows to easily display
/// some text with custom style and color on a render target.
///
/// It inherits all the functions from `sf::Transformable`:
/// position, rotation, scale, origin. It also adds text-specific
/// properties such as the font to use, the character size,
/// the font style (bold, italic, underlined and strike through), the
/// text color, the outline thickness, the outline color, the character
/// spacing, the line spacing and the text to display of course.
/// It also provides convenience functions to calculate the
/// graphical size of the text, or to get the global position
/// of a given character.
///
/// `sf::Text` works in combination with the `sf::Font` class, which
/// loads and provides the glyphs (visual characters) of a given font.
///
/// The separation of `sf::Font` and `sf::Text` allows more flexibility
/// and better performances: indeed a `sf::Font` is a heavy resource,
/// and any operation on it is slow (often too slow for real-time
/// applications). On the other side, a `sf::Text` is a lightweight
/// object which can combine the glyphs data and metrics of a `sf::Font`
/// to display any text on a render target.
///
/// It is important to note that the `sf::Text` instance doesn't
/// copy the font that it uses, it only keeps a reference to it.
/// Thus, a `sf::Font` must not be destructed while it is
/// used by a `sf::Text` (i.e. never write a function that
/// uses a local `sf::Font` instance for creating a text).
///
/// See also the note on coordinates and undistorted rendering in `sf::Transformable`.
///
/// Usage example:
/// \code
/// // Open a font
/// const sf::Font font("arial.ttf");
///
/// // Create a text
/// sf::Text text(font, "hello");
/// text.setCharacterSize(30);
/// text.setStyle(sf::Text::Bold);
/// text.setFillColor(sf::Color::Red);
///
/// // Draw it
/// window.draw(text);
/// \endcode
///
/// \see `sf::Font`, `sf::Transformable`
///
////////////////////////////////////////////////////////////

View File

@ -1,874 +0,0 @@
////////////////////////////////////////////////////////////
//
// SFML - Simple and Fast Multimedia Library
// Copyright (C) 2007-2025 Laurent Gomila (laurent@sfml-dev.org)
//
// This software is provided 'as-is', without any express or implied warranty.
// In no event will the authors be held liable for any damages arising from the use of this software.
//
// Permission is granted to anyone to use this software for any purpose,
// including commercial applications, and to alter it and redistribute it freely,
// subject to the following restrictions:
//
// 1. The origin of this software must not be misrepresented;
// you must not claim that you wrote the original software.
// If you use this software in a product, an acknowledgment
// in the product documentation would be appreciated but is not required.
//
// 2. Altered source versions must be plainly marked as such,
// and must not be misrepresented as being the original software.
//
// 3. This notice may not be removed or altered from any source distribution.
//
////////////////////////////////////////////////////////////
#pragma once
////////////////////////////////////////////////////////////
// Headers
////////////////////////////////////////////////////////////
#include <SFML/Graphics/Export.hpp>
#include <SFML/Graphics/CoordinateType.hpp>
#include <SFML/Graphics/Rect.hpp>
#include <SFML/Window/GlResource.hpp>
#include <SFML/System/Vector2.hpp>
#include <filesystem>
#include <cstddef>
#include <cstdint>
namespace sf
{
class InputStream;
class Window;
class Image;
////////////////////////////////////////////////////////////
/// \brief Image living on the graphics card that can be used for drawing
///
////////////////////////////////////////////////////////////
class SFML_GRAPHICS_API Texture : GlResource
{
public:
////////////////////////////////////////////////////////////
/// \brief Default constructor
///
/// Creates a texture with width 0 and height 0.
///
/// \see `resize`
///
////////////////////////////////////////////////////////////
Texture();
////////////////////////////////////////////////////////////
/// \brief Destructor
///
////////////////////////////////////////////////////////////
~Texture();
////////////////////////////////////////////////////////////
/// \brief Copy constructor
///
/// \param copy instance to copy
///
////////////////////////////////////////////////////////////
Texture(const Texture& copy);
////////////////////////////////////////////////////////////
/// \brief Copy assignment operator
///
////////////////////////////////////////////////////////////
Texture& operator=(const Texture&);
////////////////////////////////////////////////////////////
/// \brief Move constructor
///
////////////////////////////////////////////////////////////
Texture(Texture&&) noexcept;
////////////////////////////////////////////////////////////
/// \brief Move assignment operator
///
////////////////////////////////////////////////////////////
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 sf::Exception 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 `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 `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 sf::Exception 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 sf::Exception 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 `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 `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 sf::Exception 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 sf::Exception 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 `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 `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 sf::Exception 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 sf::Exception 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 `area` argument is used to load only a sub-rectangle
/// of the whole image.
/// If the `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 sf::Exception 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 sf::Exception if construction was unsuccessful
///
////////////////////////////////////////////////////////////
explicit Texture(Vector2u size, bool sRgb = false);
////////////////////////////////////////////////////////////
/// \brief Resize the texture
///
/// If this function fails, the texture is left unchanged.
///
/// \param size Width and height of the texture
/// \param sRgb `true` to enable sRGB conversion, `false` to disable it
///
/// \return `true` if resizing was successful, `false` if it failed
///
////////////////////////////////////////////////////////////
[[nodiscard]] bool resize(Vector2u size, bool sRgb = false);
////////////////////////////////////////////////////////////
/// \brief Load the texture from a file on disk
///
/// The `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 `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 `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 = {});
////////////////////////////////////////////////////////////
/// \brief Load the texture from a file in memory
///
/// The `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 `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 `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 = {});
////////////////////////////////////////////////////////////
/// \brief Load the texture from a custom stream
///
/// The `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 `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 `true` if loading was successful, `false` if it failed
///
/// \see `loadFromFile`, `loadFromMemory`, `loadFromImage`
///
////////////////////////////////////////////////////////////
[[nodiscard]] bool loadFromStream(InputStream& stream, bool sRgb = false, const IntRect& area = {});
////////////////////////////////////////////////////////////
/// \brief Load the texture from an image
///
/// The `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 `area` rectangle crosses the bounds of the image, it
/// is adjusted to fit the image size.
///
/// The maximum size for a texture depends on the graphics
/// driver and can be retrieved with the `getMaximumSize` function.
///
/// If this function fails, the texture is left unchanged.
///
/// \param image Image to load into the texture
/// \param sRgb `true` to enable sRGB conversion, `false` to disable it
/// \param area Area of the image to load
///
/// \return `true` if loading was successful, `false` if it failed
///
/// \see `loadFromFile`, `loadFromMemory`
///
////////////////////////////////////////////////////////////
[[nodiscard]] bool loadFromImage(const Image& image, bool sRgb = false, const IntRect& area = {});
////////////////////////////////////////////////////////////
/// \brief Return the size of the texture
///
/// \return Size in pixels
///
////////////////////////////////////////////////////////////
[[nodiscard]] Vector2u getSize() const;
////////////////////////////////////////////////////////////
/// \brief Copy the texture pixels to an image
///
/// This function performs a slow operation that downloads
/// the texture's pixels from the graphics card and copies
/// them to a new image, potentially applying transformations
/// to pixels if necessary (texture may be padded or flipped).
///
/// \return Image containing the texture's pixels
///
/// \see `loadFromImage`
///
////////////////////////////////////////////////////////////
[[nodiscard]] Image copyToImage() const;
////////////////////////////////////////////////////////////
/// \brief Update the whole texture from an array of pixels
///
/// The pixel array is assumed to have the same size as
/// the `area` rectangle, and to contain 32-bits RGBA pixels.
///
/// No additional check is performed on the size of the pixel
/// array. Passing invalid arguments will lead to an undefined
/// behavior.
///
/// This function does nothing if `pixels` is `nullptr`
/// or if the texture was not previously created.
///
/// \param pixels Array of pixels to copy to the texture
///
////////////////////////////////////////////////////////////
void update(const std::uint8_t* pixels);
////////////////////////////////////////////////////////////
/// \brief Update a part of the texture from an array of pixels
///
/// The size of the pixel array must match the `size` argument,
/// and it must contain 32-bits RGBA pixels.
///
/// No additional check is performed on the size of the pixel
/// array or the bounds of the area to update. Passing invalid
/// arguments will lead to an undefined behavior.
///
/// This function does nothing if `pixels` is null or if the
/// texture was not previously created.
///
/// \param pixels Array of pixels to copy to the texture
/// \param size Width and height of the pixel region contained in `pixels`
/// \param dest Coordinates of the destination position
///
////////////////////////////////////////////////////////////
void update(const std::uint8_t* pixels, Vector2u size, Vector2u dest);
////////////////////////////////////////////////////////////
/// \brief Update a part of this texture from another texture
///
/// Although the source texture can be smaller than this texture,
/// this function is usually used for updating the whole texture.
/// The other overload, which has an additional destination
/// argument, is more convenient for updating a sub-area of this
/// texture.
///
/// No additional check is performed on the size of the passed
/// texture. Passing a texture bigger than this texture
/// will lead to an undefined behavior.
///
/// This function does nothing if either texture was not
/// previously created.
///
/// \param texture Source texture to copy to this texture
///
////////////////////////////////////////////////////////////
void update(const Texture& texture);
////////////////////////////////////////////////////////////
/// \brief Update a part of this texture from another texture
///
/// No additional check is performed on the size of the texture.
/// Passing an invalid combination of texture size and destination
/// will lead to an undefined behavior.
///
/// This function does nothing if either texture was not
/// previously created.
///
/// \param texture Source texture to copy to this texture
/// \param dest Coordinates of the destination position
///
////////////////////////////////////////////////////////////
void update(const Texture& texture, Vector2u dest);
////////////////////////////////////////////////////////////
/// \brief Update the texture from an image
///
/// Although the source image can be smaller than the texture,
/// this function is usually used for updating the whole texture.
/// The other overload, which has an additional destination
/// argument, is more convenient for updating a sub-area of the
/// texture.
///
/// No additional check is performed on the size of the image.
/// Passing an image bigger than the texture will lead to an
/// undefined behavior.
///
/// This function does nothing if the texture was not
/// previously created.
///
/// \param image Image to copy to the texture
///
////////////////////////////////////////////////////////////
void update(const Image& image);
////////////////////////////////////////////////////////////
/// \brief Update a part of the texture from an image
///
/// No additional check is performed on the size of the image.
/// Passing an invalid combination of image size and destination
/// will lead to an undefined behavior.
///
/// This function does nothing if the texture was not
/// previously created.
///
/// \param image Image to copy to the texture
/// \param dest Coordinates of the destination position
///
////////////////////////////////////////////////////////////
void update(const Image& image, Vector2u dest);
////////////////////////////////////////////////////////////
/// \brief Update the texture from the contents of a window
///
/// Although the source window can be smaller than the texture,
/// this function is usually used for updating the whole texture.
/// The other overload, which has an additional destination
/// argument, is more convenient for updating a sub-area of the
/// texture.
///
/// No additional check is performed on the size of the window.
/// Passing a window bigger than the texture will lead to an
/// undefined behavior.
///
/// This function does nothing if either the texture or the window
/// was not previously created.
///
/// \param window Window to copy to the texture
///
////////////////////////////////////////////////////////////
void update(const Window& window);
////////////////////////////////////////////////////////////
/// \brief Update a part of the texture from the contents of a window
///
/// No additional check is performed on the size of the window.
/// Passing an invalid combination of window size and destination
/// will lead to an undefined behavior.
///
/// This function does nothing if either the texture or the window
/// was not previously created.
///
/// \param window Window to copy to the texture
/// \param dest Coordinates of the destination position
///
////////////////////////////////////////////////////////////
void update(const Window& window, Vector2u dest);
////////////////////////////////////////////////////////////
/// \brief Enable or disable the smooth filter
///
/// When the filter is activated, the texture appears smoother
/// so that pixels are less noticeable. However if you want
/// the texture to look exactly the same as its source file,
/// you should leave it disabled.
/// The smooth filter is disabled by default.
///
/// \param smooth `true` to enable smoothing, `false` to disable it
///
/// \see `isSmooth`
///
////////////////////////////////////////////////////////////
void setSmooth(bool smooth);
////////////////////////////////////////////////////////////
/// \brief Tell whether the smooth filter is enabled or not
///
/// \return `true` if smoothing is enabled, `false` if it is disabled
///
/// \see `setSmooth`
///
////////////////////////////////////////////////////////////
[[nodiscard]] bool isSmooth() const;
////////////////////////////////////////////////////////////
/// \brief Tell whether the texture source is converted from sRGB or not
///
/// \return `true` if the texture source is converted from sRGB, `false` if not
///
/// \see `setSrgb`
///
////////////////////////////////////////////////////////////
[[nodiscard]] bool isSrgb() const;
////////////////////////////////////////////////////////////
/// \brief Enable or disable repeating
///
/// Repeating is involved when using texture coordinates
/// outside the texture rectangle [0, 0, width, height].
/// In this case, if repeat mode is enabled, the whole texture
/// will be repeated as many times as needed to reach the
/// coordinate (for example, if the X texture coordinate is
/// 3 * width, the texture will be repeated 3 times).
/// If repeat mode is disabled, the "extra space" will instead
/// be filled with border pixels.
/// Warning: on very old graphics cards, white pixels may appear
/// when the texture is repeated. With such cards, repeat mode
/// can be used reliably only if the texture has power-of-two
/// dimensions (such as 256x128).
/// Repeating is disabled by default.
///
/// \param repeated `true` to repeat the texture, `false` to disable repeating
///
/// \see `isRepeated`
///
////////////////////////////////////////////////////////////
void setRepeated(bool repeated);
////////////////////////////////////////////////////////////
/// \brief Tell whether the texture is repeated or not
///
/// \return `true` if repeat mode is enabled, `false` if it is disabled
///
/// \see `setRepeated`
///
////////////////////////////////////////////////////////////
[[nodiscard]] bool isRepeated() const;
////////////////////////////////////////////////////////////
/// \brief Generate a mipmap using the current texture data
///
/// Mipmaps are pre-computed chains of optimized textures. Each
/// level of texture in a mipmap is generated by halving each of
/// the previous level's dimensions. This is done until the final
/// level has the size of 1x1. The textures generated in this process may
/// make use of more advanced filters which might improve the visual quality
/// of textures when they are applied to objects much smaller than they are.
/// This is known as minification. Because fewer texels (texture elements)
/// have to be sampled from when heavily minified, usage of mipmaps
/// can also improve rendering performance in certain scenarios.
///
/// Mipmap generation relies on the necessary OpenGL extension being
/// available. If it is unavailable or generation fails due to another
/// reason, this function will return `false`. Mipmap data is only valid from
/// the time it is generated until the next time the base level image is
/// modified, at which point this function will have to be called again to
/// regenerate it.
///
/// \return `true` if mipmap generation was successful, `false` if unsuccessful
///
////////////////////////////////////////////////////////////
[[nodiscard]] bool generateMipmap();
////////////////////////////////////////////////////////////
/// \brief Swap the contents of this texture with those of another
///
/// \param right Instance to swap with
///
////////////////////////////////////////////////////////////
void swap(Texture& right) noexcept;
////////////////////////////////////////////////////////////
/// \brief Get the underlying OpenGL handle of the texture.
///
/// You shouldn't need to use this function, unless you have
/// very specific stuff to implement that SFML doesn't support,
/// or implement a temporary workaround until a bug is fixed.
///
/// \return OpenGL handle of the texture or 0 if not yet created
///
////////////////////////////////////////////////////////////
[[nodiscard]] unsigned int getNativeHandle() const;
////////////////////////////////////////////////////////////
/// \brief Bind a texture for rendering
///
/// This function is not part of the graphics API, it mustn't be
/// used when drawing SFML entities. It must be used only if you
/// mix `sf::Texture` with OpenGL code.
///
/// \code
/// sf::Texture t1, t2;
/// ...
/// sf::Texture::bind(&t1);
/// // draw OpenGL stuff that use t1...
/// sf::Texture::bind(&t2);
/// // draw OpenGL stuff that use t2...
/// sf::Texture::bind(nullptr);
/// // draw OpenGL stuff that use no texture...
/// \endcode
///
/// The `coordinateType` argument controls how texture
/// coordinates will be interpreted. If Normalized (the default), they
/// must be in range [0 .. 1], which is the default way of handling
/// texture coordinates with OpenGL. If Pixels, they must be given
/// in pixels (range [0 .. size]). This mode is used internally by
/// the graphics classes of SFML, it makes the definition of texture
/// coordinates more intuitive for the high-level API, users don't need
/// to compute normalized values.
///
/// \param texture Pointer to the texture to bind, can be null to use no texture
/// \param coordinateType Type of texture coordinates to use
///
////////////////////////////////////////////////////////////
static void bind(const Texture* texture, CoordinateType coordinateType = CoordinateType::Normalized);
////////////////////////////////////////////////////////////
/// \brief Get the maximum texture size allowed
///
/// This maximum size is defined by the graphics driver.
/// You can expect a value of 512 pixels for low-end graphics
/// card, and up to 8192 pixels or more for newer hardware.
///
/// \return Maximum size allowed for textures, in pixels
///
////////////////////////////////////////////////////////////
[[nodiscard]] static unsigned int getMaximumSize();
private:
friend class Text;
friend class RenderTexture;
friend class RenderTarget;
////////////////////////////////////////////////////////////
/// \brief Get a valid image size according to hardware support
///
/// This function checks whether the graphics driver supports
/// non power of two sizes or not, and adjusts the size
/// accordingly.
/// The returned size is greater than or equal to the original size.
///
/// \param size size to convert
///
/// \return Valid nearest size (greater than or equal to specified size)
///
////////////////////////////////////////////////////////////
[[nodiscard]] static unsigned int getValidSize(unsigned int size);
////////////////////////////////////////////////////////////
/// \brief Invalidate the mipmap if one exists
///
/// This also resets the texture's minifying function.
/// This function is mainly for internal use by RenderTexture.
///
////////////////////////////////////////////////////////////
void invalidateMipmap();
////////////////////////////////////////////////////////////
// Member data
////////////////////////////////////////////////////////////
Vector2u m_size; //!< Public texture size
Vector2u m_actualSize; //!< Actual texture size (can be greater than public size because of padding)
unsigned int m_texture{}; //!< Internal texture identifier
bool m_isSmooth{}; //!< Status of the smooth filter
bool m_sRgb{}; //!< Should the texture source be converted from sRGB?
bool m_isRepeated{}; //!< Is the texture in repeat mode?
mutable bool m_pixelsFlipped{}; //!< To work around the inconsistency in Y orientation
bool m_fboAttachment{}; //!< Is this texture owned by a framebuffer object?
bool m_hasMipmap{}; //!< Has the mipmap been generated?
std::uint64_t m_cacheId; //!< Unique number that identifies the texture to the render target's cache
};
////////////////////////////////////////////////////////////
/// \brief Swap the contents of one texture with those of another
///
/// \param left First instance to swap
/// \param right Second instance to swap
///
////////////////////////////////////////////////////////////
SFML_GRAPHICS_API void swap(Texture& left, Texture& right) noexcept;
} // namespace sf
////////////////////////////////////////////////////////////
/// \class sf::Texture
/// \ingroup graphics
///
/// `sf::Texture` stores pixels that can be drawn, with a sprite
/// for example. A texture lives in the graphics card memory,
/// therefore it is very fast to draw a texture to a render target,
/// or copy a render target to a texture (the graphics card can
/// access both directly).
///
/// Being stored in the graphics card memory has some drawbacks.
/// A texture cannot be manipulated as freely as a `sf::Image`,
/// you need to prepare the pixels first and then upload them
/// to the texture in a single operation (see `Texture::update`).
///
/// `sf::Texture` makes it easy to convert from/to `sf::Image`, but
/// keep in mind that these calls require transfers between
/// the graphics card and the central memory, therefore they are
/// slow operations.
///
/// A texture can be loaded from an image, but also directly
/// from a file/memory/stream. The necessary shortcuts are defined
/// so that you don't need an image first for the most common cases.
/// 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(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
/// accessed individually. Therefore, if you need to read the texture's
/// pixels (like for pixel-perfect collisions), it is recommended to
/// store the collision information separately, for example in an array
/// of booleans.
///
/// Like `sf::Image`, `sf::Texture` can handle a unique internal
/// representation of pixels, which is RGBA 32 bits. This means
/// that a pixel must be composed of 8 bit red, green, blue and
/// alpha channels -- just like a `sf::Color`.
///
/// When providing texture data from an image file or memory, it can
/// either be stored in a linear color space or an sRGB color space.
/// Most digital images account for gamma correction already, so they
/// would need to be "uncorrected" back to linear color space before
/// being processed by the hardware. The hardware can automatically
/// convert it from the sRGB color space to a linear color space when
/// it gets sampled. When the rendered image gets output to the final
/// framebuffer, it gets converted back to sRGB.
///
/// This option is only useful in conjunction with an sRGB capable
/// framebuffer. This can be requested during window creation.
///
/// Usage example:
/// \code
/// // This example shows the most common use of sf::Texture:
/// // drawing a sprite
///
/// // Load a texture from a file
/// const sf::Texture texture("texture.png");
///
/// // Assign it to a sprite
/// sf::Sprite sprite(texture);
///
/// // Draw the textured sprite
/// window.draw(sprite);
/// \endcode
///
/// \code
/// // This example shows another common use of sf::Texture:
/// // streaming real-time data, like video frames
///
/// // Create an empty texture
/// sf::Texture texture({640, 480});
///
/// // Create a sprite that will display the texture
/// sf::Sprite sprite(texture);
///
/// while (...) // the main loop
/// {
/// ...
///
/// // update the texture
/// std::uint8_t* pixels = ...; // get a fresh chunk of pixels (the next frame of a movie, for example)
/// texture.update(pixels);
///
/// // draw it
/// window.draw(sprite);
///
/// ...
/// }
///
/// \endcode
///
/// Like `sf::Shader` that can be used as a raw OpenGL shader,
/// `sf::Texture` can also be used directly as a raw texture for
/// custom OpenGL geometry.
/// \code
/// sf::Texture::bind(&texture);
/// ... render OpenGL geometry ...
/// sf::Texture::bind(nullptr);
/// \endcode
///
/// \see `sf::Sprite`, `sf::Image`, `sf::RenderTexture`
///
////////////////////////////////////////////////////////////

View File

@ -1,393 +0,0 @@
////////////////////////////////////////////////////////////
//
// SFML - Simple and Fast Multimedia Library
// Copyright (C) 2007-2025 Laurent Gomila (laurent@sfml-dev.org)
//
// This software is provided 'as-is', without any express or implied warranty.
// In no event will the authors be held liable for any damages arising from the use of this software.
//
// Permission is granted to anyone to use this software for any purpose,
// including commercial applications, and to alter it and redistribute it freely,
// subject to the following restrictions:
//
// 1. The origin of this software must not be misrepresented;
// you must not claim that you wrote the original software.
// If you use this software in a product, an acknowledgment
// in the product documentation would be appreciated but is not required.
//
// 2. Altered source versions must be plainly marked as such,
// and must not be misrepresented as being the original software.
//
// 3. This notice may not be removed or altered from any source distribution.
//
////////////////////////////////////////////////////////////
#pragma once
////////////////////////////////////////////////////////////
// Headers
////////////////////////////////////////////////////////////
#include <SFML/Graphics/Export.hpp>
#include <SFML/Graphics/Rect.hpp>
#include <SFML/System/Vector2.hpp>
#include <array>
namespace sf
{
class Angle;
////////////////////////////////////////////////////////////
/// \brief 3x3 transform matrix
///
////////////////////////////////////////////////////////////
class Transform
{
public:
////////////////////////////////////////////////////////////
/// \brief Default constructor
///
/// Creates an identity transform (a transform that does nothing).
///
////////////////////////////////////////////////////////////
constexpr Transform() = default;
////////////////////////////////////////////////////////////
/// \brief Construct a transform from a 3x3 matrix
///
/// \param a00 Element (0, 0) of the matrix
/// \param a01 Element (0, 1) of the matrix
/// \param a02 Element (0, 2) of the matrix
/// \param a10 Element (1, 0) of the matrix
/// \param a11 Element (1, 1) of the matrix
/// \param a12 Element (1, 2) of the matrix
/// \param a20 Element (2, 0) of the matrix
/// \param a21 Element (2, 1) of the matrix
/// \param a22 Element (2, 2) of the matrix
///
////////////////////////////////////////////////////////////
constexpr Transform(float a00, float a01, float a02, float a10, float a11, float a12, float a20, float a21, float a22);
////////////////////////////////////////////////////////////
/// \brief Return the transform as a 4x4 matrix
///
/// This function returns a pointer to an array of 16 floats
/// containing the transform elements as a 4x4 matrix, which
/// is directly compatible with OpenGL functions.
///
/// \code
/// sf::Transform transform = ...;
/// glLoadMatrixf(transform.getMatrix());
/// \endcode
///
/// \return Pointer to a 4x4 matrix
///
////////////////////////////////////////////////////////////
[[nodiscard]] constexpr const float* getMatrix() const;
////////////////////////////////////////////////////////////
/// \brief Return the inverse of the transform
///
/// If the inverse cannot be computed, an identity transform
/// is returned.
///
/// \return A new transform which is the inverse of self
///
////////////////////////////////////////////////////////////
[[nodiscard]] constexpr Transform getInverse() const;
////////////////////////////////////////////////////////////
/// \brief Transform a 2D point
///
/// These two statements are equivalent:
/// \code
/// sf::Vector2f transformedPoint = matrix.transformPoint(point);
/// sf::Vector2f transformedPoint = matrix * point;
/// \endcode
///
/// \param point Point to transform
///
/// \return Transformed point
///
////////////////////////////////////////////////////////////
[[nodiscard]] constexpr Vector2f transformPoint(Vector2f point) const;
////////////////////////////////////////////////////////////
/// \brief Transform a rectangle
///
/// Since SFML doesn't provide support for oriented rectangles,
/// the result of this function is always an axis-aligned
/// rectangle. Which means that if the transform contains a
/// rotation, the bounding rectangle of the transformed rectangle
/// is returned.
///
/// \param rectangle Rectangle to transform
///
/// \return Transformed rectangle
///
////////////////////////////////////////////////////////////
[[nodiscard]] constexpr FloatRect transformRect(const FloatRect& rectangle) const;
////////////////////////////////////////////////////////////
/// \brief Combine the current transform with another one
///
/// The result is a transform that is equivalent to applying
/// `transform` followed by `*this`. Mathematically, it is
/// equivalent to a matrix multiplication `(*this) * transform`.
///
/// These two statements are equivalent:
/// \code
/// left.combine(right);
/// left *= right;
/// \endcode
///
/// \param transform Transform to combine with this transform
///
/// \return Reference to `*this`
///
////////////////////////////////////////////////////////////
constexpr Transform& combine(const Transform& transform);
////////////////////////////////////////////////////////////
/// \brief Combine the current transform with a translation
///
/// This function returns a reference to `*this`, so that calls
/// can be chained.
/// \code
/// sf::Transform transform;
/// transform.translate(sf::Vector2f(100, 200)).rotate(sf::degrees(45));
/// \endcode
///
/// \param offset Translation offset to apply
///
/// \return Reference to `*this`
///
/// \see `rotate`, `scale`
///
////////////////////////////////////////////////////////////
constexpr Transform& translate(Vector2f offset);
////////////////////////////////////////////////////////////
/// \brief Combine the current transform with a rotation
///
/// This function returns a reference to `*this`, so that calls
/// can be chained.
/// \code
/// sf::Transform transform;
/// transform.rotate(sf::degrees(90)).translate(50, 20);
/// \endcode
///
/// \param angle Rotation angle
///
/// \return Reference to `*this`
///
/// \see `translate`, `scale`
///
////////////////////////////////////////////////////////////
SFML_GRAPHICS_API Transform& rotate(Angle angle);
////////////////////////////////////////////////////////////
/// \brief Combine the current transform with a rotation
///
/// The center of rotation is provided for convenience as a second
/// argument, so that you can build rotations around arbitrary points
/// more easily (and efficiently) than the usual
/// `translate(-center).rotate(angle).translate(center)`.
///
/// This function returns a reference to `*this`, so that calls
/// can be chained.
/// \code
/// sf::Transform transform;
/// transform.rotate(sf::degrees(90), sf::Vector2f(8, 3)).translate(sf::Vector2f(50, 20));
/// \endcode
///
/// \param angle Rotation angle
/// \param center Center of rotation
///
/// \return Reference to `*this`
///
/// \see `translate`, `scale`
///
////////////////////////////////////////////////////////////
SFML_GRAPHICS_API Transform& rotate(Angle angle, Vector2f center);
////////////////////////////////////////////////////////////
/// \brief Combine the current transform with a scaling
///
/// This function returns a reference to `*this`, so that calls
/// can be chained.
/// \code
/// sf::Transform transform;
/// transform.scale(sf::Vector2f(2, 1)).rotate(sf::degrees(45));
/// \endcode
///
/// \param factors Scaling factors
///
/// \return Reference to `*this`
///
/// \see `translate`, `rotate`
///
////////////////////////////////////////////////////////////
constexpr Transform& scale(Vector2f factors);
////////////////////////////////////////////////////////////
/// \brief Combine the current transform with a scaling
///
/// The center of scaling is provided for convenience as a second
/// argument, so that you can build scaling around arbitrary points
/// more easily (and efficiently) than the usual
/// `translate(-center).scale(factors).translate(center)`.
///
/// This function returns a reference to `*this`, so that calls
/// can be chained.
/// \code
/// sf::Transform transform;
/// transform.scale(sf::Vector2f(2, 1), sf::Vector2f(8, 3)).rotate(45);
/// \endcode
///
/// \param factors Scaling factors
/// \param center Center of scaling
///
/// \return Reference to `*this`
///
/// \see `translate`, `rotate`
///
////////////////////////////////////////////////////////////
constexpr Transform& scale(Vector2f factors, Vector2f center);
////////////////////////////////////////////////////////////
// Static member data
////////////////////////////////////////////////////////////
// NOLINTNEXTLINE(readability-identifier-naming)
static const Transform Identity; //!< The identity transform (does nothing)
private:
////////////////////////////////////////////////////////////
// Member data
////////////////////////////////////////////////////////////
// clang-format off
std::array<float, 16> m_matrix{1.f, 0.f, 0.f, 0.f,
0.f, 1.f, 0.f, 0.f,
0.f, 0.f, 1.f, 0.f,
0.f, 0.f, 0.f, 1.f}; //!< 4x4 matrix defining the transformation
// clang-format off
};
////////////////////////////////////////////////////////////
/// \relates sf::Transform
/// \brief Overload of binary `operator*` to combine two transforms
///
/// This call is equivalent to calling `Transform(left).combine(right)`.
///
/// \param left Left operand (the first transform)
/// \param right Right operand (the second transform)
///
/// \return New combined transform
///
////////////////////////////////////////////////////////////
[[nodiscard]] constexpr Transform operator*(const Transform& left, const Transform& right);
////////////////////////////////////////////////////////////
/// \relates sf::Transform
/// \brief Overload of binary `operator*=` to combine two transforms
///
/// This call is equivalent to calling `left.combine(right)`.
///
/// \param left Left operand (the first transform)
/// \param right Right operand (the second transform)
///
/// \return The combined transform
///
////////////////////////////////////////////////////////////
constexpr Transform& operator*=(Transform& left, const Transform& right);
////////////////////////////////////////////////////////////
/// \relates sf::Transform
/// \brief Overload of binary `operator*` to transform a point
///
/// This call is equivalent to calling `left.transformPoint(right)`.
///
/// \param left Left operand (the transform)
/// \param right Right operand (the point to transform)
///
/// \return New transformed point
///
////////////////////////////////////////////////////////////
[[nodiscard]] constexpr Vector2f operator*(const Transform& left, Vector2f right);
////////////////////////////////////////////////////////////
/// \relates sf::Transform
/// \brief Overload of binary `operator==` to compare two transforms
///
/// Performs an element-wise comparison of the elements of the
/// left transform with the elements of the right transform.
///
/// \param left Left operand (the first transform)
/// \param right Right operand (the second transform)
///
/// \return `true` if the transforms are equal, `false` otherwise
///
////////////////////////////////////////////////////////////
[[nodiscard]] constexpr bool operator==(const Transform& left, const Transform& right);
////////////////////////////////////////////////////////////
/// \relates sf::Transform
/// \brief Overload of binary `operator!=` to compare two transforms
///
/// This call is equivalent to `!(left == right)`.
///
/// \param left Left operand (the first transform)
/// \param right Right operand (the second transform)
///
/// \return `true` if the transforms are not equal, `false` otherwise
///
////////////////////////////////////////////////////////////
[[nodiscard]] constexpr bool operator!=(const Transform& left, const Transform& right);
} // namespace sf
#include <SFML/Graphics/Transform.inl>
////////////////////////////////////////////////////////////
/// \class sf::Transform
/// \ingroup graphics
///
/// A `sf::Transform` specifies how to translate, rotate, scale,
/// shear, project, whatever things. In mathematical terms, it defines
/// how to transform a coordinate system into another.
///
/// For example, if you apply a rotation transform to a sprite, the
/// result will be a rotated sprite. And anything that is transformed
/// by this rotation transform will be rotated the same way, according
/// to its initial position.
///
/// Transforms are typically used for drawing. But they can also be
/// used for any computation that requires to transform points between
/// the local and global coordinate systems of an entity (like collision
/// detection).
///
/// Example:
/// \code
/// // define a translation transform
/// sf::Transform translation;
/// translation.translate(20, 50);
///
/// // define a rotation transform
/// sf::Transform rotation;
/// rotation.rotate(45);
///
/// // combine them
/// sf::Transform transform = translation * rotation;
///
/// // use the result to transform stuff...
/// sf::Vector2f point = transform.transformPoint({10, 20});
/// sf::FloatRect rect = transform.transformRect(sf::FloatRect({0, 0}, {10, 100}));
/// \endcode
///
/// \see `sf::Transformable`, `sf::RenderStates`
///
////////////////////////////////////////////////////////////

View File

@ -1,236 +0,0 @@
////////////////////////////////////////////////////////////
//
// SFML - Simple and Fast Multimedia Library
// Copyright (C) 2007-2025 Laurent Gomila (laurent@sfml-dev.org)
//
// This software is provided 'as-is', without any express or implied warranty.
// In no event will the authors be held liable for any damages arising from the use of this software.
//
// Permission is granted to anyone to use this software for any purpose,
// including commercial applications, and to alter it and redistribute it freely,
// subject to the following restrictions:
//
// 1. The origin of this software must not be misrepresented;
// you must not claim that you wrote the original software.
// If you use this software in a product, an acknowledgment
// in the product documentation would be appreciated but is not required.
//
// 2. Altered source versions must be plainly marked as such,
// and must not be misrepresented as being the original software.
//
// 3. This notice may not be removed or altered from any source distribution.
//
////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////
// Headers
////////////////////////////////////////////////////////////
#include <SFML/Graphics/Transform.hpp> // NOLINT(misc-header-include-cycle)
#include <array>
#include <cstddef>
namespace sf
{
////////////////////////////////////////////////////////////
// clang-format off
constexpr Transform::Transform(float a00, float a01, float a02,
float a10, float a11, float a12,
float a20, float a21, float a22)
: m_matrix{a00, a10, 0.f, a20,
a01, a11, 0.f, a21,
0.f, 0.f, 1.f, 0.f,
a02, a12, 0.f, a22}
{
}
// clang-format on
////////////////////////////////////////////////////////////
constexpr const float* Transform::getMatrix() const
{
return m_matrix.data();
}
////////////////////////////////////////////////////////////
constexpr Transform Transform::getInverse() const
{
// clang-format off
// Compute the determinant
const float det = m_matrix[0] * (m_matrix[15] * m_matrix[5] - m_matrix[7] * m_matrix[13]) -
m_matrix[1] * (m_matrix[15] * m_matrix[4] - m_matrix[7] * m_matrix[12]) +
m_matrix[3] * (m_matrix[13] * m_matrix[4] - m_matrix[5] * m_matrix[12]);
// clang-format on
// Compute the inverse if the determinant is not zero
// (don't use an epsilon because the determinant may *really* be tiny)
if (det != 0.f)
{
// clang-format off
return {(m_matrix[15] * m_matrix[5] - m_matrix[7] * m_matrix[13]) / det,
-(m_matrix[15] * m_matrix[4] - m_matrix[7] * m_matrix[12]) / det,
(m_matrix[13] * m_matrix[4] - m_matrix[5] * m_matrix[12]) / det,
-(m_matrix[15] * m_matrix[1] - m_matrix[3] * m_matrix[13]) / det,
(m_matrix[15] * m_matrix[0] - m_matrix[3] * m_matrix[12]) / det,
-(m_matrix[13] * m_matrix[0] - m_matrix[1] * m_matrix[12]) / det,
(m_matrix[7] * m_matrix[1] - m_matrix[3] * m_matrix[5]) / det,
-(m_matrix[7] * m_matrix[0] - m_matrix[3] * m_matrix[4]) / det,
(m_matrix[5] * m_matrix[0] - m_matrix[1] * m_matrix[4]) / det};
// clang-format on
}
return Identity;
}
////////////////////////////////////////////////////////////
constexpr Vector2f Transform::transformPoint(Vector2f point) const
{
return {m_matrix[0] * point.x + m_matrix[4] * point.y + m_matrix[12],
m_matrix[1] * point.x + m_matrix[5] * point.y + m_matrix[13]};
}
////////////////////////////////////////////////////////////
constexpr FloatRect Transform::transformRect(const FloatRect& rectangle) const
{
// Transform the 4 corners of the rectangle
const std::array points = {transformPoint(rectangle.position),
transformPoint(rectangle.position + Vector2f(0.f, rectangle.size.y)),
transformPoint(rectangle.position + Vector2f(rectangle.size.x, 0.f)),
transformPoint(rectangle.position + rectangle.size)};
// Compute the bounding rectangle of the transformed points
Vector2f pmin = points[0];
Vector2f pmax = points[0];
for (std::size_t i = 1; i < points.size(); ++i)
{
// clang-format off
if (points[i].x < pmin.x) pmin.x = points[i].x;
else if (points[i].x > pmax.x) pmax.x = points[i].x;
if (points[i].y < pmin.y) pmin.y = points[i].y;
else if (points[i].y > pmax.y) pmax.y = points[i].y;
// clang-format on
}
return {pmin, pmax - pmin};
}
////////////////////////////////////////////////////////////
constexpr Transform& Transform::combine(const Transform& transform)
{
const auto& a = m_matrix;
const auto& b = transform.m_matrix;
// clang-format off
*this = Transform(a[0] * b[0] + a[4] * b[1] + a[12] * b[3],
a[0] * b[4] + a[4] * b[5] + a[12] * b[7],
a[0] * b[12] + a[4] * b[13] + a[12] * b[15],
a[1] * b[0] + a[5] * b[1] + a[13] * b[3],
a[1] * b[4] + a[5] * b[5] + a[13] * b[7],
a[1] * b[12] + a[5] * b[13] + a[13] * b[15],
a[3] * b[0] + a[7] * b[1] + a[15] * b[3],
a[3] * b[4] + a[7] * b[5] + a[15] * b[7],
a[3] * b[12] + a[7] * b[13] + a[15] * b[15]);
// clang-format on
return *this;
}
////////////////////////////////////////////////////////////
constexpr Transform& Transform::translate(Vector2f offset)
{
// clang-format off
const Transform translation(1, 0, offset.x,
0, 1, offset.y,
0, 0, 1);
// clang-format on
return combine(translation);
}
////////////////////////////////////////////////////////////
constexpr Transform& Transform::scale(Vector2f factors)
{
// clang-format off
const Transform scaling(factors.x, 0, 0,
0, factors.y, 0,
0, 0, 1);
// clang-format on
return combine(scaling);
}
////////////////////////////////////////////////////////////
constexpr Transform& Transform::scale(Vector2f factors, Vector2f center)
{
// clang-format off
const Transform scaling(factors.x, 0, center.x * (1 - factors.x),
0, factors.y, center.y * (1 - factors.y),
0, 0, 1);
// clang-format on
return combine(scaling);
}
////////////////////////////////////////////////////////////
constexpr Transform operator*(const Transform& left, const Transform& right)
{
return Transform(left).combine(right);
}
////////////////////////////////////////////////////////////
constexpr Transform& operator*=(Transform& left, const Transform& right)
{
return left.combine(right);
}
////////////////////////////////////////////////////////////
constexpr Vector2f operator*(const Transform& left, Vector2f right)
{
return left.transformPoint(right);
}
////////////////////////////////////////////////////////////
constexpr bool operator==(const Transform& left, const Transform& right)
{
const float* a = left.getMatrix();
const float* b = right.getMatrix();
// clang-format off
return ((a[0] == b[0]) && (a[1] == b[1]) && (a[3] == b[3]) &&
(a[4] == b[4]) && (a[5] == b[5]) && (a[7] == b[7]) &&
(a[12] == b[12]) && (a[13] == b[13]) && (a[15] == b[15]));
// clang-format on
}
////////////////////////////////////////////////////////////
constexpr bool operator!=(const Transform& left, const Transform& right)
{
return !(left == right);
}
////////////////////////////////////////////////////////////
// Static member data
////////////////////////////////////////////////////////////
// Note: the 'inline' keyword here is technically not required, but VS2019 fails
// to compile with a bogus "multiple definition" error if not explicitly used.
inline constexpr Transform Transform::Identity;
} // namespace sf

View File

@ -1,340 +0,0 @@
////////////////////////////////////////////////////////////
//
// SFML - Simple and Fast Multimedia Library
// Copyright (C) 2007-2025 Laurent Gomila (laurent@sfml-dev.org)
//
// This software is provided 'as-is', without any express or implied warranty.
// In no event will the authors be held liable for any damages arising from the use of this software.
//
// Permission is granted to anyone to use this software for any purpose,
// including commercial applications, and to alter it and redistribute it freely,
// subject to the following restrictions:
//
// 1. The origin of this software must not be misrepresented;
// you must not claim that you wrote the original software.
// If you use this software in a product, an acknowledgment
// in the product documentation would be appreciated but is not required.
//
// 2. Altered source versions must be plainly marked as such,
// and must not be misrepresented as being the original software.
//
// 3. This notice may not be removed or altered from any source distribution.
//
////////////////////////////////////////////////////////////
#pragma once
////////////////////////////////////////////////////////////
// Headers
////////////////////////////////////////////////////////////
#include <SFML/Graphics/Export.hpp>
#include <SFML/Graphics/Transform.hpp>
#include <SFML/System/Angle.hpp>
namespace sf
{
////////////////////////////////////////////////////////////
/// \brief Decomposed transform defined by a position, a rotation and a scale
///
////////////////////////////////////////////////////////////
class SFML_GRAPHICS_API Transformable
{
public:
////////////////////////////////////////////////////////////
/// \brief Default constructor
///
////////////////////////////////////////////////////////////
Transformable() = default;
////////////////////////////////////////////////////////////
/// \brief Virtual destructor
///
////////////////////////////////////////////////////////////
virtual ~Transformable() = default;
////////////////////////////////////////////////////////////
/// \brief set the position of the object
///
/// This function completely overwrites the previous position.
/// See the move function to apply an offset based on the previous position instead.
/// The default position of a transformable object is (0, 0).
///
/// \param position New position
///
/// \see `move`, `getPosition`
///
////////////////////////////////////////////////////////////
void setPosition(Vector2f position);
////////////////////////////////////////////////////////////
/// \brief set the orientation of the object
///
/// This function completely overwrites the previous rotation.
/// See the rotate function to add an angle based on the previous rotation instead.
/// The default rotation of a transformable object is 0.
///
/// \param angle New rotation
///
/// \see `rotate`, `getRotation`
///
////////////////////////////////////////////////////////////
void setRotation(Angle angle);
////////////////////////////////////////////////////////////
/// \brief set the scale factors of the object
///
/// This function completely overwrites the previous scale.
/// See the scale function to add a factor based on the previous scale instead.
/// The default scale of a transformable object is (1, 1).
///
/// \param factors New scale factors
///
/// \see `scale`, `getScale`
///
////////////////////////////////////////////////////////////
void setScale(Vector2f factors);
////////////////////////////////////////////////////////////
/// \brief set the local origin of the object
///
/// The origin of an object defines the center point for
/// all transformations (position, scale, rotation).
/// The coordinates of this point must be relative to the
/// top-left corner of the object, and ignore all
/// transformations (position, scale, rotation).
/// The default origin of a transformable object is (0, 0).
///
/// \param origin New origin
///
/// \see `getOrigin`
///
////////////////////////////////////////////////////////////
void setOrigin(Vector2f origin);
////////////////////////////////////////////////////////////
/// \brief get the position of the object
///
/// \return Current position
///
/// \see `setPosition`
///
////////////////////////////////////////////////////////////
[[nodiscard]] Vector2f getPosition() const;
////////////////////////////////////////////////////////////
/// \brief get the orientation of the object
///
/// The rotation is always in the range [0, 360].
///
/// \return Current rotation
///
/// \see `setRotation`
///
////////////////////////////////////////////////////////////
[[nodiscard]] Angle getRotation() const;
////////////////////////////////////////////////////////////
/// \brief get the current scale of the object
///
/// \return Current scale factors
///
/// \see `setScale`
///
////////////////////////////////////////////////////////////
[[nodiscard]] Vector2f getScale() const;
////////////////////////////////////////////////////////////
/// \brief get the local origin of the object
///
/// \return Current origin
///
/// \see `setOrigin`
///
////////////////////////////////////////////////////////////
[[nodiscard]] Vector2f getOrigin() const;
////////////////////////////////////////////////////////////
/// \brief Move the object by a given offset
///
/// This function adds to the current position of the object,
/// unlike `setPosition` which overwrites it.
/// Thus, it is equivalent to the following code:
/// \code
/// object.setPosition(object.getPosition() + offset);
/// \endcode
///
/// \param offset Offset
///
/// \see `setPosition`
///
////////////////////////////////////////////////////////////
void move(Vector2f offset);
////////////////////////////////////////////////////////////
/// \brief Rotate the object
///
/// This function adds to the current rotation of the object,
/// unlike `setRotation` which overwrites it.
/// Thus, it is equivalent to the following code:
/// \code
/// object.setRotation(object.getRotation() + angle);
/// \endcode
///
/// \param angle Angle of rotation
///
////////////////////////////////////////////////////////////
void rotate(Angle angle);
////////////////////////////////////////////////////////////
/// \brief Scale the object
///
/// This function multiplies the current scale of the object,
/// unlike `setScale` which overwrites it.
/// Thus, it is equivalent to the following code:
/// \code
/// sf::Vector2f scale = object.getScale();
/// object.setScale(scale.x * factor.x, scale.y * factor.y);
/// \endcode
///
/// \param factor Scale factors
///
/// \see `setScale`
///
////////////////////////////////////////////////////////////
void scale(Vector2f factor);
////////////////////////////////////////////////////////////
/// \brief get the combined transform of the object
///
/// \return Transform combining the position/rotation/scale/origin of the object
///
/// \see `getInverseTransform`
///
////////////////////////////////////////////////////////////
[[nodiscard]] const Transform& getTransform() const;
////////////////////////////////////////////////////////////
/// \brief get the inverse of the combined transform of the object
///
/// \return Inverse of the combined transformations applied to the object
///
/// \see `getTransform`
///
////////////////////////////////////////////////////////////
[[nodiscard]] const Transform& getInverseTransform() const;
private:
////////////////////////////////////////////////////////////
// Member data
////////////////////////////////////////////////////////////
Vector2f m_origin; //!< Origin of translation/rotation/scaling of the object
Vector2f m_position; //!< Position of the object in the 2D world
Angle m_rotation; //!< Orientation of the object
Vector2f m_scale{1, 1}; //!< Scale of the object
mutable Transform m_transform; //!< Combined transformation of the object
mutable Transform m_inverseTransform; //!< Combined transformation of the object
mutable bool m_transformNeedUpdate{true}; //!< Does the transform need to be recomputed?
mutable bool m_inverseTransformNeedUpdate{true}; //!< Does the transform need to be recomputed?
};
} // namespace sf
////////////////////////////////////////////////////////////
/// \class sf::Transformable
/// \ingroup graphics
///
/// This class is provided for convenience, on top of `sf::Transform`.
///
/// `sf::Transform`, as a low-level class, offers a great level of
/// flexibility but it is not always convenient to manage. Indeed,
/// one can easily combine any kind of operation, such as a translation
/// followed by a rotation followed by a scaling, but once the result
/// transform is built, there's no way to go backward and, let's say,
/// change only the rotation without modifying the translation and scaling.
/// The entire transform must be recomputed, which means that you
/// need to retrieve the initial translation and scale factors as
/// well, and combine them the same way you did before updating the
/// rotation. This is a tedious operation, and it requires to store
/// all the individual components of the final transform.
///
/// That's exactly what `sf::Transformable` was written for: it hides
/// these variables and the composed transform behind an easy to use
/// interface. You can set or get any of the individual components
/// without worrying about the others. It also provides the composed
/// transform (as a `sf::Transform`), and keeps it up-to-date.
///
/// In addition to the position, rotation and scale, `sf::Transformable`
/// provides an "origin" component, which represents the local origin
/// of the three other components. Let's take an example with a 10x10
/// pixels sprite. By default, the sprite is positioned/rotated/scaled
/// relative to its top-left corner, because it is the local point
/// (0, 0). But if we change the origin to be (5, 5), the sprite will
/// be positioned/rotated/scaled around its center instead. And if
/// we set the origin to (10, 10), it will be transformed around its
/// bottom-right corner.
///
/// To keep the `sf::Transformable` class simple, there's only one
/// origin for all the components. You cannot position the sprite
/// relative to its top-left corner while rotating it around its
/// center, for example. To do such things, use `sf::Transform` directly.
///
/// `sf::Transformable` can be used as a base class. It is often
/// combined with `sf::Drawable` -- that's what SFML's sprites,
/// texts and shapes do.
/// \code
/// class MyEntity : public sf::Transformable, public sf::Drawable
/// {
/// void draw(sf::RenderTarget& target, sf::RenderStates states) const override
/// {
/// states.transform *= getTransform();
/// target.draw(..., states);
/// }
/// };
///
/// MyEntity entity;
/// entity.setPosition({10, 20});
/// entity.setRotation(sf::degrees(45));
/// window.draw(entity);
/// \endcode
///
/// It can also be used as a member, if you don't want to use
/// its API directly (because you don't need all its functions,
/// or you have different naming conventions for example).
/// \code
/// class MyEntity
/// {
/// public:
/// void SetPosition(const MyVector& v)
/// {
/// myTransform.setPosition(v.x(), v.y());
/// }
///
/// void Draw(sf::RenderTarget& target) const
/// {
/// target.draw(..., myTransform.getTransform());
/// }
///
/// private:
/// sf::Transformable myTransform;
/// };
/// \endcode
///
/// A note on coordinates and undistorted rendering: \n
/// By default, SFML (or more exactly, OpenGL) may interpolate drawable objects
/// such as sprites or texts when rendering. While this allows transitions
/// like slow movements or rotations to appear smoothly, it can lead to
/// unwanted results in some cases, for example blurred or distorted objects.
/// In order to render a `sf::Drawable` object pixel-perfectly, make sure
/// the involved coordinates allow a 1:1 mapping of pixels in the window
/// to texels (pixels in the texture). More specifically, this means:
/// * The object's position, origin and scale have no fractional part
/// * The object's and the view's rotation are a multiple of 90 degrees
/// * The view's center and size have no fractional part
///
/// \see `sf::Transform`
///
////////////////////////////////////////////////////////////

View File

@ -1,122 +0,0 @@
////////////////////////////////////////////////////////////
//
// SFML - Simple and Fast Multimedia Library
// Copyright (C) 2007-2025 Laurent Gomila (laurent@sfml-dev.org)
//
// This software is provided 'as-is', without any express or implied warranty.
// In no event will the authors be held liable for any damages arising from the use of this software.
//
// Permission is granted to anyone to use this software for any purpose,
// including commercial applications, and to alter it and redistribute it freely,
// subject to the following restrictions:
//
// 1. The origin of this software must not be misrepresented;
// you must not claim that you wrote the original software.
// If you use this software in a product, an acknowledgment
// in the product documentation would be appreciated but is not required.
//
// 2. Altered source versions must be plainly marked as such,
// and must not be misrepresented as being the original software.
//
// 3. This notice may not be removed or altered from any source distribution.
//
////////////////////////////////////////////////////////////
#pragma once
////////////////////////////////////////////////////////////
// Headers
////////////////////////////////////////////////////////////
#include <SFML/Graphics/Color.hpp>
#include <SFML/System/Vector2.hpp>
namespace sf
{
////////////////////////////////////////////////////////////
/// \brief Point with color and texture coordinates
///
/// By default, the vertex color is white and texture coordinates are (0, 0).
///
////////////////////////////////////////////////////////////
struct Vertex
{
////////////////////////////////////////////////////////////
// Member data
////////////////////////////////////////////////////////////
Vector2f position; //!< 2D position of the vertex
Color color{Color::White}; //!< Color of the vertex
Vector2f texCoords{}; //!< Coordinates of the texture's pixel to map to the vertex NOLINT(readability-redundant-member-init)
};
} // namespace sf
////////////////////////////////////////////////////////////
/// \struct sf::Vertex
/// \ingroup graphics
///
/// A vertex is an improved point. It has a position and other
/// extra attributes that will be used for drawing: in SFML,
/// vertices also have a color and a pair of texture coordinates.
///
/// The vertex is the building block of drawing. Everything which
/// is visible on screen is made of vertices. They are grouped
/// as 2D primitives (lines, triangles, ...), and these primitives
/// are grouped to create even more complex 2D entities such as
/// sprites, texts, etc.
///
/// If you use the graphical entities of SFML (sprite, text, shape)
/// you won't have to deal with vertices directly. But if you want
/// to define your own 2D entities, such as tiled maps or particle
/// systems, using vertices will allow you to get maximum performances.
///
/// Example:
/// \code
/// // define a 100x100 square, red, with a 10x10 texture mapped on it
/// sf::Vertex vertices[]
/// {
/// {{ 0.0f, 0.0f}, sf::Color::Red, { 0.0f, 0.0f}},
/// {{ 0.0f, 100.0f}, sf::Color::Red, { 0.0f, 10.0f}},
/// {{100.0f, 100.0f}, sf::Color::Red, {10.0f, 10.0f}},
/// {{ 0.0f, 0.0f}, sf::Color::Red, { 0.0f, 0.0f}},
/// {{100.0f, 100.0f}, sf::Color::Red, {10.0f, 10.0f}},
/// {{100.0f, 0.0f}, sf::Color::Red, {10.0f, 0.0f}}
/// };
///
/// // draw it
/// window.draw(vertices, 6, sf::PrimitiveType::Triangles);
/// \endcode
///
///
/// It is recommended to use aggregate initialization to create vertex
/// objects, which initializes the members in order.
///
/// On a C++20-compliant compiler (or where supported as an extension)
/// it is possible to use "designated initializers" to only initialize
/// a subset of members, with the restriction of having to follow the
/// same order in which they are defined.
///
/// Example:
/// \code
/// // C++17 and above
/// sf::Vertex v0{{5.0f, 5.0f}}; // explicit 'position', implicit 'color' and 'texCoords'
/// sf::Vertex v1{{5.0f, 5.0f}, sf::Color::Red}; // explicit 'position' and 'color', implicit 'texCoords'
/// sf::Vertex v2{{5.0f, 5.0f}, sf::Color::Red, {1.0f, 1.0f}}; // everything is explicitly specified
///
/// // C++20 and above (or compilers supporting "designated initializers" as an extension)
/// sf::Vertex v3{
/// .position{5.0f, 5.0f},
/// .texCoords{1.0f, 1.0f}
/// };
/// \endcode
///
///
/// Note: Although texture coordinates are supposed to be an integer
/// amount of pixels, their type is float because of some buggy graphics
/// drivers that are not able to process integer coordinates correctly.
///
/// \see `sf::VertexArray`
///
////////////////////////////////////////////////////////////

View File

@ -1,221 +0,0 @@
////////////////////////////////////////////////////////////
//
// SFML - Simple and Fast Multimedia Library
// Copyright (C) 2007-2025 Laurent Gomila (laurent@sfml-dev.org)
//
// This software is provided 'as-is', without any express or implied warranty.
// In no event will the authors be held liable for any damages arising from the use of this software.
//
// Permission is granted to anyone to use this software for any purpose,
// including commercial applications, and to alter it and redistribute it freely,
// subject to the following restrictions:
//
// 1. The origin of this software must not be misrepresented;
// you must not claim that you wrote the original software.
// If you use this software in a product, an acknowledgment
// in the product documentation would be appreciated but is not required.
//
// 2. Altered source versions must be plainly marked as such,
// and must not be misrepresented as being the original software.
//
// 3. This notice may not be removed or altered from any source distribution.
//
////////////////////////////////////////////////////////////
#pragma once
////////////////////////////////////////////////////////////
// Headers
////////////////////////////////////////////////////////////
#include <SFML/Graphics/Export.hpp>
#include <SFML/Graphics/Drawable.hpp>
#include <SFML/Graphics/PrimitiveType.hpp>
#include <SFML/Graphics/Rect.hpp>
#include <SFML/Graphics/RenderStates.hpp>
#include <SFML/Graphics/Vertex.hpp>
#include <vector>
#include <cstddef>
namespace sf
{
class RenderTarget;
////////////////////////////////////////////////////////////
/// \brief Set of one or more 2D primitives
///
////////////////////////////////////////////////////////////
class SFML_GRAPHICS_API VertexArray : public Drawable
{
public:
////////////////////////////////////////////////////////////
/// \brief Default constructor
///
/// Creates an empty vertex array.
///
////////////////////////////////////////////////////////////
VertexArray() = default;
////////////////////////////////////////////////////////////
/// \brief Construct the vertex array with a type and an initial number of vertices
///
/// \param type Type of primitives
/// \param vertexCount Initial number of vertices in the array
///
////////////////////////////////////////////////////////////
explicit VertexArray(PrimitiveType type, std::size_t vertexCount = 0);
////////////////////////////////////////////////////////////
/// \brief Return the vertex count
///
/// \return Number of vertices in the array
///
////////////////////////////////////////////////////////////
[[nodiscard]] std::size_t getVertexCount() const;
////////////////////////////////////////////////////////////
/// \brief Get a read-write access to a vertex by its index
///
/// This function doesn't check `index`, it must be in range
/// [0, `getVertexCount()` - 1]. The behavior is undefined
/// otherwise.
///
/// \param index Index of the vertex to get
///
/// \return Reference to the `index`-th vertex
///
/// \see `getVertexCount`
///
////////////////////////////////////////////////////////////
[[nodiscard]] Vertex& operator[](std::size_t index);
////////////////////////////////////////////////////////////
/// \brief Get a read-only access to a vertex by its index
///
/// This function doesn't check `index`, it must be in range
/// [0, `getVertexCount()` - 1]. The behavior is undefined
/// otherwise.
///
/// \param index Index of the vertex to get
///
/// \return Const reference to the `index`-th vertex
///
/// \see `getVertexCount`
///
////////////////////////////////////////////////////////////
[[nodiscard]] const Vertex& operator[](std::size_t index) const;
////////////////////////////////////////////////////////////
/// \brief Clear the vertex array
///
/// This function removes all the vertices from the array.
/// It doesn't deallocate the corresponding memory, so that
/// adding new vertices after clearing doesn't involve
/// reallocating all the memory.
///
////////////////////////////////////////////////////////////
void clear();
////////////////////////////////////////////////////////////
/// \brief Resize the vertex array
///
/// If `vertexCount` is greater than the current size, the previous
/// vertices are kept and new (default-constructed) vertices are
/// added.
/// If `vertexCount` is less than the current size, existing vertices
/// are removed from the array.
///
/// \param vertexCount New size of the array (number of vertices)
///
////////////////////////////////////////////////////////////
void resize(std::size_t vertexCount);
////////////////////////////////////////////////////////////
/// \brief Add a vertex to the array
///
/// \param vertex Vertex to add
///
////////////////////////////////////////////////////////////
void append(const Vertex& vertex);
////////////////////////////////////////////////////////////
/// \brief Set the type of primitives to draw
///
/// This function defines how the vertices must be interpreted
/// when it's time to draw them:
/// \li As points
/// \li As lines
/// \li As triangles
/// The default primitive type is `sf::PrimitiveType::Points`.
///
/// \param type Type of primitive
///
////////////////////////////////////////////////////////////
void setPrimitiveType(PrimitiveType type);
////////////////////////////////////////////////////////////
/// \brief Get the type of primitives drawn by the vertex array
///
/// \return Primitive type
///
////////////////////////////////////////////////////////////
[[nodiscard]] PrimitiveType getPrimitiveType() const;
////////////////////////////////////////////////////////////
/// \brief Compute the bounding rectangle of the vertex array
///
/// This function returns the minimal axis-aligned rectangle
/// that contains all the vertices of the array.
///
/// \return Bounding rectangle of the vertex array
///
////////////////////////////////////////////////////////////
[[nodiscard]] FloatRect getBounds() const;
private:
////////////////////////////////////////////////////////////
/// \brief Draw the vertex array to a render target
///
/// \param target Render target to draw to
/// \param states Current render states
///
////////////////////////////////////////////////////////////
void draw(RenderTarget& target, RenderStates states) const override;
////////////////////////////////////////////////////////////
// Member data
////////////////////////////////////////////////////////////
std::vector<Vertex> m_vertices; //!< Vertices contained in the array
PrimitiveType m_primitiveType{PrimitiveType::Points}; //!< Type of primitives to draw
};
} // namespace sf
////////////////////////////////////////////////////////////
/// \class sf::VertexArray
/// \ingroup graphics
///
/// `sf::VertexArray` is a very simple wrapper around a dynamic
/// array of vertices and a primitives type.
///
/// It inherits `sf::Drawable`, but unlike other drawables it
/// is not transformable.
///
/// Example:
/// \code
/// sf::VertexArray lines(sf::PrimitiveType::LineStrip, 4);
/// lines[0].position = sf::Vector2f(10, 0);
/// lines[1].position = sf::Vector2f(20, 0);
/// lines[2].position = sf::Vector2f(30, 5);
/// lines[3].position = sf::Vector2f(40, 2);
///
/// window.draw(lines);
/// \endcode
///
/// \see `sf::Vertex`
///
////////////////////////////////////////////////////////////

View File

@ -1,414 +0,0 @@
////////////////////////////////////////////////////////////
//
// SFML - Simple and Fast Multimedia Library
// Copyright (C) 2007-2025 Laurent Gomila (laurent@sfml-dev.org)
//
// This software is provided 'as-is', without any express or implied warranty.
// In no event will the authors be held liable for any damages arising from the use of this software.
//
// Permission is granted to anyone to use this software for any purpose,
// including commercial applications, and to alter it and redistribute it freely,
// subject to the following restrictions:
//
// 1. The origin of this software must not be misrepresented;
// you must not claim that you wrote the original software.
// If you use this software in a product, an acknowledgment
// in the product documentation would be appreciated but is not required.
//
// 2. Altered source versions must be plainly marked as such,
// and must not be misrepresented as being the original software.
//
// 3. This notice may not be removed or altered from any source distribution.
//
////////////////////////////////////////////////////////////
#pragma once
////////////////////////////////////////////////////////////
// Headers
////////////////////////////////////////////////////////////
#include <SFML/Graphics/Export.hpp>
#include <SFML/Graphics/Drawable.hpp>
#include <SFML/Graphics/PrimitiveType.hpp>
#include <SFML/Graphics/RenderStates.hpp>
#include <SFML/Window/GlResource.hpp>
#include <cstddef>
namespace sf
{
class RenderTarget;
struct Vertex;
////////////////////////////////////////////////////////////
/// \brief Vertex buffer storage for one or more 2D primitives
///
////////////////////////////////////////////////////////////
class SFML_GRAPHICS_API VertexBuffer : public Drawable, private GlResource
{
public:
////////////////////////////////////////////////////////////
/// \brief Usage specifiers
///
/// If data is going to be updated once or more every frame,
/// set the usage to Stream. If data is going to be set once
/// and used for a long time without being modified, set the
/// usage to Static. For everything else Dynamic should be a
/// good compromise.
///
////////////////////////////////////////////////////////////
enum class Usage
{
Stream, //!< Constantly changing data
Dynamic, //!< Occasionally changing data
Static //!< Rarely changing data
};
////////////////////////////////////////////////////////////
/// \brief Default constructor
///
/// Creates an empty vertex buffer.
///
////////////////////////////////////////////////////////////
VertexBuffer() = default;
////////////////////////////////////////////////////////////
/// \brief Construct a `VertexBuffer` with a specific `PrimitiveType`
///
/// Creates an empty vertex buffer and sets its primitive type to \p type.
///
/// \param type Type of primitive
///
////////////////////////////////////////////////////////////
explicit VertexBuffer(PrimitiveType type);
////////////////////////////////////////////////////////////
/// \brief Construct a `VertexBuffer` with a specific usage specifier
///
/// Creates an empty vertex buffer and sets its usage to \p usage.
///
/// \param usage Usage specifier
///
////////////////////////////////////////////////////////////
explicit VertexBuffer(Usage usage);
////////////////////////////////////////////////////////////
/// \brief Construct a `VertexBuffer` with a specific `PrimitiveType` and usage specifier
///
/// Creates an empty vertex buffer and sets its primitive type
/// to \p type and usage to \p usage.
///
/// \param type Type of primitive
/// \param usage Usage specifier
///
////////////////////////////////////////////////////////////
VertexBuffer(PrimitiveType type, Usage usage);
////////////////////////////////////////////////////////////
/// \brief Copy constructor
///
/// \param copy instance to copy
///
////////////////////////////////////////////////////////////
VertexBuffer(const VertexBuffer& copy);
////////////////////////////////////////////////////////////
/// \brief Destructor
///
////////////////////////////////////////////////////////////
~VertexBuffer() override;
////////////////////////////////////////////////////////////
/// \brief Create the vertex buffer
///
/// Creates the vertex buffer and allocates enough graphics
/// memory to hold `vertexCount` vertices. Any previously
/// allocated memory is freed in the process.
///
/// In order to deallocate previously allocated memory pass 0
/// as `vertexCount`. Don't forget to recreate with a non-zero
/// value when graphics memory should be allocated again.
///
/// \param vertexCount Number of vertices worth of memory to allocate
///
/// \return `true` if creation was successful
///
////////////////////////////////////////////////////////////
[[nodiscard]] bool create(std::size_t vertexCount);
////////////////////////////////////////////////////////////
/// \brief Return the vertex count
///
/// \return Number of vertices in the vertex buffer
///
////////////////////////////////////////////////////////////
[[nodiscard]] std::size_t getVertexCount() const;
////////////////////////////////////////////////////////////
/// \brief Update the whole buffer from an array of vertices
///
/// The vertex array is assumed to have the same size as
/// the created buffer.
///
/// No additional check is performed on the size of the vertex
/// array. Passing invalid arguments will lead to undefined
/// behavior.
///
/// This function does nothing if `vertices` is null or if the
/// buffer was not previously created.
///
/// \param vertices Array of vertices to copy to the buffer
///
/// \return `true` if the update was successful
///
////////////////////////////////////////////////////////////
[[nodiscard]] bool update(const Vertex* vertices);
////////////////////////////////////////////////////////////
/// \brief Update a part of the buffer from an array of vertices
///
/// `offset` is specified as the number of vertices to skip
/// from the beginning of the buffer.
///
/// If `offset` is 0 and `vertexCount` is equal to the size of
/// the currently created buffer, its whole contents are replaced.
///
/// If `offset` is 0 and `vertexCount` is greater than the
/// size of the currently created buffer, a new buffer is created
/// containing the vertex data.
///
/// If `offset` is 0 and `vertexCount` is less than the size of
/// the currently created buffer, only the corresponding region
/// is updated.
///
/// If `offset` is not 0 and `offset` + `vertexCount` is greater
/// than the size of the currently created buffer, the update fails.
///
/// No additional check is performed on the size of the vertex
/// array. Passing invalid arguments will lead to undefined
/// behavior.
///
/// \param vertices Array of vertices to copy to the buffer
/// \param vertexCount Number of vertices to copy
/// \param offset Offset in the buffer to copy to
///
/// \return `true` if the update was successful
///
////////////////////////////////////////////////////////////
[[nodiscard]] bool update(const Vertex* vertices, std::size_t vertexCount, unsigned int offset);
////////////////////////////////////////////////////////////
/// \brief Copy the contents of another buffer into this buffer
///
/// \param vertexBuffer Vertex buffer whose contents to copy into this vertex buffer
///
/// \return `true` if the copy was successful
///
////////////////////////////////////////////////////////////
[[nodiscard]] bool update(const VertexBuffer& vertexBuffer);
////////////////////////////////////////////////////////////
/// \brief Overload of assignment operator
///
/// \param right Instance to assign
///
/// \return Reference to self
///
////////////////////////////////////////////////////////////
VertexBuffer& operator=(const VertexBuffer& right);
////////////////////////////////////////////////////////////
/// \brief Swap the contents of this vertex buffer with those of another
///
/// \param right Instance to swap with
///
////////////////////////////////////////////////////////////
void swap(VertexBuffer& right) noexcept;
////////////////////////////////////////////////////////////
/// \brief Get the underlying OpenGL handle of the vertex buffer.
///
/// You shouldn't need to use this function, unless you have
/// very specific stuff to implement that SFML doesn't support,
/// or implement a temporary workaround until a bug is fixed.
///
/// \return OpenGL handle of the vertex buffer or 0 if not yet created
///
////////////////////////////////////////////////////////////
[[nodiscard]] unsigned int getNativeHandle() const;
////////////////////////////////////////////////////////////
/// \brief Set the type of primitives to draw
///
/// This function defines how the vertices must be interpreted
/// when it's time to draw them.
///
/// The default primitive type is `sf::PrimitiveType::Points`.
///
/// \param type Type of primitive
///
////////////////////////////////////////////////////////////
void setPrimitiveType(PrimitiveType type);
////////////////////////////////////////////////////////////
/// \brief Get the type of primitives drawn by the vertex buffer
///
/// \return Primitive type
///
////////////////////////////////////////////////////////////
[[nodiscard]] PrimitiveType getPrimitiveType() const;
////////////////////////////////////////////////////////////
/// \brief Set the usage specifier of this vertex buffer
///
/// This function provides a hint about how this vertex buffer is
/// going to be used in terms of data update frequency.
///
/// After changing the usage specifier, the vertex buffer has
/// to be updated with new data for the usage specifier to
/// take effect.
///
/// The default usage type is `sf::VertexBuffer::Usage::Stream`.
///
/// \param usage Usage specifier
///
////////////////////////////////////////////////////////////
void setUsage(Usage usage);
////////////////////////////////////////////////////////////
/// \brief Get the usage specifier of this vertex buffer
///
/// \return Usage specifier
///
////////////////////////////////////////////////////////////
[[nodiscard]] Usage getUsage() const;
////////////////////////////////////////////////////////////
/// \brief Bind a vertex buffer for rendering
///
/// This function is not part of the graphics API, it mustn't be
/// used when drawing SFML entities. It must be used only if you
/// mix `sf::VertexBuffer` with OpenGL code.
///
/// \code
/// sf::VertexBuffer vb1, vb2;
/// ...
/// sf::VertexBuffer::bind(&vb1);
/// // draw OpenGL stuff that use vb1...
/// sf::VertexBuffer::bind(&vb2);
/// // draw OpenGL stuff that use vb2...
/// sf::VertexBuffer::bind(nullptr);
/// // draw OpenGL stuff that use no vertex buffer...
/// \endcode
///
/// \param vertexBuffer Pointer to the vertex buffer to bind, can be null to use no vertex buffer
///
////////////////////////////////////////////////////////////
static void bind(const VertexBuffer* vertexBuffer);
////////////////////////////////////////////////////////////
/// \brief Tell whether or not the system supports vertex buffers
///
/// This function should always be called before using
/// the vertex buffer features. If it returns `false`, then
/// any attempt to use `sf::VertexBuffer` will fail.
///
/// \return `true` if vertex buffers are supported, `false` otherwise
///
////////////////////////////////////////////////////////////
[[nodiscard]] static bool isAvailable();
private:
////////////////////////////////////////////////////////////
/// \brief Draw the vertex buffer to a render target
///
/// \param target Render target to draw to
/// \param states Current render states
///
////////////////////////////////////////////////////////////
void draw(RenderTarget& target, RenderStates states) const override;
////////////////////////////////////////////////////////////
// Member data
////////////////////////////////////////////////////////////
unsigned int m_buffer{}; //!< Internal buffer identifier
std::size_t m_size{}; //!< Size in Vertices of the currently allocated buffer
PrimitiveType m_primitiveType{PrimitiveType::Points}; //!< Type of primitives to draw
Usage m_usage{Usage::Stream}; //!< How this vertex buffer is to be used
};
////////////////////////////////////////////////////////////
/// \brief Swap the contents of one vertex buffer with those of another
///
/// \param left First instance to swap
/// \param right Second instance to swap
///
////////////////////////////////////////////////////////////
SFML_GRAPHICS_API void swap(VertexBuffer& left, VertexBuffer& right) noexcept;
} // namespace sf
////////////////////////////////////////////////////////////
/// \class sf::VertexBuffer
/// \ingroup graphics
///
/// `sf::VertexBuffer` is a simple wrapper around a dynamic
/// buffer of vertices and a primitives type.
///
/// Unlike `sf::VertexArray`, the vertex data is stored in
/// graphics memory.
///
/// In situations where a large amount of vertex data would
/// have to be transferred from system memory to graphics memory
/// every frame, using `sf::VertexBuffer` can help. By using a
/// `sf::VertexBuffer`, data that has not been changed between frames
/// does not have to be re-transferred from system to graphics
/// memory as would be the case with `sf::VertexArray`. If data transfer
/// is a bottleneck, this can lead to performance gains.
///
/// Using `sf::VertexBuffer`, the user also has the ability to only modify
/// a portion of the buffer in graphics memory. This way, a large buffer
/// can be allocated at the start of the application and only the
/// applicable portions of it need to be updated during the course of
/// the application. This allows the user to take full control of data
/// transfers between system and graphics memory if they need to.
///
/// In special cases, the user can make use of multiple threads to update
/// vertex data in multiple distinct regions of the buffer simultaneously.
/// This might make sense when e.g. the position of multiple objects has to
/// be recalculated very frequently. The computation load can be spread
/// across multiple threads as long as there are no other data dependencies.
///
/// Simultaneous updates to the vertex buffer are not guaranteed to be
/// carried out by the driver in any specific order. Updating the same
/// region of the buffer from multiple threads will not cause undefined
/// behavior, however the final state of the buffer will be unpredictable.
///
/// Simultaneous updates of distinct non-overlapping regions of the buffer
/// are also not guaranteed to complete in a specific order. However, in
/// this case the user can make sure to synchronize the writer threads at
/// well-defined points in their code. The driver will make sure that all
/// pending data transfers complete before the vertex buffer is sourced
/// by the rendering pipeline.
///
/// It inherits `sf::Drawable`, but unlike other drawables it
/// is not transformable.
///
/// Example:
/// \code
/// std::array<sf::Vertex, 15> vertices;
/// ...
/// sf::VertexBuffer triangles(sf::PrimitiveType::Triangles);
/// triangles.create(vertices.size());
/// triangles.update(vertices.data());
/// ...
/// window.draw(triangles);
/// \endcode
///
/// \see `sf::Vertex`, `sf::VertexArray`
///
////////////////////////////////////////////////////////////

View File

@ -1,357 +0,0 @@
////////////////////////////////////////////////////////////
//
// SFML - Simple and Fast Multimedia Library
// Copyright (C) 2007-2025 Laurent Gomila (laurent@sfml-dev.org)
//
// This software is provided 'as-is', without any express or implied warranty.
// In no event will the authors be held liable for any damages arising from the use of this software.
//
// Permission is granted to anyone to use this software for any purpose,
// including commercial applications, and to alter it and redistribute it freely,
// subject to the following restrictions:
//
// 1. The origin of this software must not be misrepresented;
// you must not claim that you wrote the original software.
// If you use this software in a product, an acknowledgment
// in the product documentation would be appreciated but is not required.
//
// 2. Altered source versions must be plainly marked as such,
// and must not be misrepresented as being the original software.
//
// 3. This notice may not be removed or altered from any source distribution.
//
////////////////////////////////////////////////////////////
#pragma once
////////////////////////////////////////////////////////////
// Headers
////////////////////////////////////////////////////////////
#include <SFML/Graphics/Export.hpp>
#include <SFML/Graphics/Rect.hpp>
#include <SFML/Graphics/Transform.hpp>
#include <SFML/System/Angle.hpp>
#include <SFML/System/Vector2.hpp>
namespace sf
{
////////////////////////////////////////////////////////////
/// \brief 2D camera that defines what region is shown on screen
///
////////////////////////////////////////////////////////////
class SFML_GRAPHICS_API View
{
public:
////////////////////////////////////////////////////////////
/// \brief Default constructor
///
/// This constructor creates a default view of (0, 0, 1000, 1000)
///
////////////////////////////////////////////////////////////
View() = default;
////////////////////////////////////////////////////////////
/// \brief Construct the view from a rectangle
///
/// \param rectangle Rectangle defining the zone to display
///
////////////////////////////////////////////////////////////
explicit View(const FloatRect& rectangle);
////////////////////////////////////////////////////////////
/// \brief Construct the view from its center and size
///
/// \param center Center of the zone to display
/// \param size Size of zone to display
///
////////////////////////////////////////////////////////////
View(Vector2f center, Vector2f size);
////////////////////////////////////////////////////////////
/// \brief Set the center of the view
///
/// \param center New center
///
/// \see `setSize`, `getCenter`
///
////////////////////////////////////////////////////////////
void setCenter(Vector2f center);
////////////////////////////////////////////////////////////
/// \brief Set the size of the view
///
/// \param size New size
///
/// \see `setCenter`, `getCenter`
///
////////////////////////////////////////////////////////////
void setSize(Vector2f size);
////////////////////////////////////////////////////////////
/// \brief Set the orientation of the view
///
/// The default rotation of a view is 0 degree.
///
/// \param angle New angle
///
/// \see `getRotation`
///
////////////////////////////////////////////////////////////
void setRotation(Angle angle);
////////////////////////////////////////////////////////////
/// \brief Set the target viewport
///
/// The viewport is the rectangle into which the contents of the
/// view are displayed, expressed as a factor (between 0 and 1)
/// of the size of the RenderTarget to which the view is applied.
/// For example, a view which takes the left side of the target would
/// be defined with `view.setViewport(sf::FloatRect({0.f, 0.f}, {0.5f, 1.f}))`.
/// By default, a view has a viewport which covers the entire target.
///
/// \param viewport New viewport rectangle
///
/// \see `getViewport`
///
////////////////////////////////////////////////////////////
void setViewport(const FloatRect& viewport);
////////////////////////////////////////////////////////////
/// \brief Set the target scissor rectangle
///
/// The scissor rectangle, expressed as a factor (between 0 and 1) of
/// the RenderTarget, specifies the region of the RenderTarget whose
/// pixels are able to be modified by draw or clear operations.
/// Any pixels which lie outside of the scissor rectangle will
/// not be modified by draw or clear operations.
/// For example, a scissor rectangle which only allows modifications
/// to the right side of the target would be defined
/// with `view.setScissor(sf::FloatRect({0.5f, 0.f}, {0.5f, 1.f}))`.
/// By default, a view has a scissor rectangle which allows
/// modifications to the entire target. This is equivalent to
/// disabling the scissor test entirely. Passing the default
/// scissor rectangle to this function will also disable
/// scissor testing.
///
/// \param scissor New scissor rectangle
///
/// \see `getScissor`
///
////////////////////////////////////////////////////////////
void setScissor(const FloatRect& scissor);
////////////////////////////////////////////////////////////
/// \brief Get the center of the view
///
/// \return Center of the view
///
/// \see `getSize`, `setCenter`
///
////////////////////////////////////////////////////////////
[[nodiscard]] Vector2f getCenter() const;
////////////////////////////////////////////////////////////
/// \brief Get the size of the view
///
/// \return Size of the view
///
/// \see `getCenter`, `setSize`
///
////////////////////////////////////////////////////////////
[[nodiscard]] Vector2f getSize() const;
////////////////////////////////////////////////////////////
/// \brief Get the current orientation of the view
///
/// \return Rotation angle of the view
///
/// \see `setRotation`
///
////////////////////////////////////////////////////////////
[[nodiscard]] Angle getRotation() const;
////////////////////////////////////////////////////////////
/// \brief Get the target viewport rectangle of the view
///
/// \return Viewport rectangle, expressed as a factor of the target size
///
/// \see `setViewport`
///
////////////////////////////////////////////////////////////
[[nodiscard]] const FloatRect& getViewport() const;
////////////////////////////////////////////////////////////
/// \brief Get the scissor rectangle of the view
///
/// \return Scissor rectangle, expressed as a factor of the target size
///
/// \see `setScissor`
///
////////////////////////////////////////////////////////////
[[nodiscard]] const FloatRect& getScissor() const;
////////////////////////////////////////////////////////////
/// \brief Move the view relative to its current position
///
/// \param offset Move offset
///
/// \see `setCenter`, `rotate`, `zoom`
///
////////////////////////////////////////////////////////////
void move(Vector2f offset);
////////////////////////////////////////////////////////////
/// \brief Rotate the view relative to its current orientation
///
/// \param angle Angle to rotate
///
/// \see `setRotation`, `move`, `zoom`
///
////////////////////////////////////////////////////////////
void rotate(Angle angle);
////////////////////////////////////////////////////////////
/// \brief Resize the view rectangle relative to its current size
///
/// Resizing the view simulates a zoom, as the zone displayed on
/// screen grows or shrinks.
/// \a factor is a multiplier:
/// \li 1 keeps the size unchanged
/// \li > 1 makes the view bigger (objects appear smaller)
/// \li < 1 makes the view smaller (objects appear bigger)
///
/// \param factor Zoom factor to apply
///
/// \see `setSize`, `move`, `rotate`
///
////////////////////////////////////////////////////////////
void zoom(float factor);
////////////////////////////////////////////////////////////
/// \brief Get the projection transform of the view
///
/// This function is meant for internal use only.
///
/// \return Projection transform defining the view
///
/// \see `getInverseTransform`
///
////////////////////////////////////////////////////////////
[[nodiscard]] const Transform& getTransform() const;
////////////////////////////////////////////////////////////
/// \brief Get the inverse projection transform of the view
///
/// This function is meant for internal use only.
///
/// \return Inverse of the projection transform defining the view
///
/// \see `getTransform`
///
////////////////////////////////////////////////////////////
[[nodiscard]] const Transform& getInverseTransform() const;
private:
////////////////////////////////////////////////////////////
// Member data
////////////////////////////////////////////////////////////
Vector2f m_center{500, 500}; //!< Center of the view, in scene coordinates
Vector2f m_size{1000, 1000}; //!< Size of the view, in scene coordinates
Angle m_rotation; //!< Angle of rotation of the view rectangle
FloatRect m_viewport{{0, 0}, {1, 1}}; //!< Viewport rectangle, expressed as a factor of the render-target's size
FloatRect m_scissor{{0, 0}, {1, 1}}; //!< Scissor rectangle, expressed as a factor of the render-target's size
mutable Transform m_transform; //!< Precomputed projection transform corresponding to the view
mutable Transform m_inverseTransform; //!< Precomputed inverse projection transform corresponding to the view
mutable bool m_transformUpdated{}; //!< Internal state telling if the transform needs to be updated
mutable bool m_invTransformUpdated{}; //!< Internal state telling if the inverse transform needs to be updated
};
} // namespace sf
////////////////////////////////////////////////////////////
/// \class sf::View
/// \ingroup graphics
///
/// `sf::View` defines a camera in the 2D scene. This is a
/// very powerful concept: you can scroll, rotate or zoom
/// the entire scene without altering the way that your
/// drawable objects are drawn.
///
/// A view is composed of a source rectangle, which defines
/// what part of the 2D scene is shown, and a target viewport,
/// which defines where the contents of the source rectangle
/// will be displayed on the render target (window or texture).
///
/// The viewport allows to map the scene to a custom part
/// of the render target, and can be used for split-screen
/// or for displaying a minimap, for example. If the source
/// rectangle doesn't have the same size as the viewport, its
/// contents will be stretched to fit in.
///
/// The scissor rectangle allows for specifying regions of the
/// render target to which modifications can be made by draw
/// and clear operations. Only pixels that are within the region
/// will be able to be modified. Pixels outside of the region will
/// not be modified by draw or clear operations.
///
/// Certain effects can be created by either using the viewport or
/// scissor rectangle. While the results appear identical, there
/// can be times where one method should be preferred over the other.
/// Viewport transformations are applied during the vertex processing
/// stage of the graphics pipeline, before the primitives are
/// rasterized into fragments for fragment processing. Since
/// viewport processing has to be performed and cannot be disabled,
/// effects that are performed using the viewport transform are
/// basically free performance-wise. Scissor testing is performed in
/// the per-sample processing stage of the graphics pipeline, after
/// fragment processing has been performed. Because per-sample
/// processing is performed at the last stage of the pipeline,
/// fragments that are discarded at this stage will cause the
/// highest waste of GPU resources compared to any method that
/// would have discarded vertices or fragments earlier in the
/// pipeline. There are situations in which scissor testing has
/// to be used to control whether fragments are discarded or not.
/// An example of such a situation is when performing the viewport
/// transform on vertices is necessary but a subset of the generated
/// fragments should not have an effect on the stencil buffer or
/// blend with the color buffer.
//
/// To apply a view, you have to assign it to the render target.
/// Then, objects drawn in this render target will be
/// affected by the view until you use another view.
///
/// Usage example:
/// \code
/// sf::RenderWindow window;
///
/// // Initialize the view to a rectangle located at (100, 100) and with a size of 400x200
/// sf::View view(sf::FloatRect({100, 100}, {400, 200}));
///
/// // Rotate it by 45 degrees
/// view.rotate(sf::degrees(45));
///
/// // Set its target viewport to be half of the window
/// view.setViewport(sf::FloatRect({0.f, 0.f}, {0.5f, 1.f}));
///
/// // Apply it
/// window.setView(view);
///
/// // Render stuff
/// window.draw(someSprite);
///
/// // Set the default view back
/// window.setView(window.getDefaultView());
///
/// // Render stuff not affected by the view
/// window.draw(someText);
/// \endcode
///
/// See also the note on coordinates and undistorted rendering in `sf::Transformable`.
///
/// \see `sf::RenderWindow`, `sf::RenderTexture`
///
////////////////////////////////////////////////////////////

View File

@ -1,39 +0,0 @@
////////////////////////////////////////////////////////////
//
// SFML - Simple and Fast Multimedia Library
// Copyright (C) 2007-2025 Laurent Gomila (laurent@sfml-dev.org)
//
// This software is provided 'as-is', without any express or implied warranty.
// In no event will the authors be held liable for any damages arising from the use of this software.
//
// Permission is granted to anyone to use this software for any purpose,
// including commercial applications, and to alter it and redistribute it freely,
// subject to the following restrictions:
//
// 1. The origin of this software must not be misrepresented;
// you must not claim that you wrote the original software.
// If you use this software in a product, an acknowledgment
// in the product documentation would be appreciated but is not required.
//
// 2. Altered source versions must be plainly marked as such,
// and must not be misrepresented as being the original software.
//
// 3. This notice may not be removed or altered from any source distribution.
//
////////////////////////////////////////////////////////////
#pragma once
////////////////////////////////////////////////////////////
// Headers
////////////////////////////////////////////////////////////
#include <SFML/Config.hpp>
#if defined(SFML_SYSTEM_IOS)
// On iOS, we have no choice but to have our own main,
// so we need to rename the user one and call it later
#define main sfmlMain
#endif

View File

@ -1,51 +0,0 @@
////////////////////////////////////////////////////////////
//
// SFML - Simple and Fast Multimedia Library
// Copyright (C) 2007-2025 Laurent Gomila (laurent@sfml-dev.org)
//
// This software is provided 'as-is', without any express or implied warranty.
// In no event will the authors be held liable for any damages arising from the use of this software.
//
// Permission is granted to anyone to use this software for any purpose,
// including commercial applications, and to alter it and redistribute it freely,
// subject to the following restrictions:
//
// 1. The origin of this software must not be misrepresented;
// you must not claim that you wrote the original software.
// If you use this software in a product, an acknowledgment
// in the product documentation would be appreciated but is not required.
//
// 2. Altered source versions must be plainly marked as such,
// and must not be misrepresented as being the original software.
//
// 3. This notice may not be removed or altered from any source distribution.
//
////////////////////////////////////////////////////////////
#pragma once
////////////////////////////////////////////////////////////
// Headers
////////////////////////////////////////////////////////////
#include <SFML/Network/Ftp.hpp>
#include <SFML/Network/Http.hpp>
#include <SFML/Network/IpAddress.hpp>
#include <SFML/Network/Packet.hpp>
#include <SFML/Network/Socket.hpp>
#include <SFML/Network/SocketHandle.hpp>
#include <SFML/Network/SocketSelector.hpp>
#include <SFML/Network/TcpListener.hpp>
#include <SFML/Network/TcpSocket.hpp>
#include <SFML/Network/UdpSocket.hpp>
#include <SFML/System.hpp>
////////////////////////////////////////////////////////////
/// \defgroup network Network module
///
/// Socket-based communication, utilities and higher-level
/// network protocols (HTTP, FTP).
///
////////////////////////////////////////////////////////////

View File

@ -1,44 +0,0 @@
////////////////////////////////////////////////////////////
//
// SFML - Simple and Fast Multimedia Library
// Copyright (C) 2007-2025 Laurent Gomila (laurent@sfml-dev.org)
//
// This software is provided 'as-is', without any express or implied warranty.
// In no event will the authors be held liable for any damages arising from the use of this software.
//
// Permission is granted to anyone to use this software for any purpose,
// including commercial applications, and to alter it and redistribute it freely,
// subject to the following restrictions:
//
// 1. The origin of this software must not be misrepresented;
// you must not claim that you wrote the original software.
// If you use this software in a product, an acknowledgment
// in the product documentation would be appreciated but is not required.
//
// 2. Altered source versions must be plainly marked as such,
// and must not be misrepresented as being the original software.
//
// 3. This notice may not be removed or altered from any source distribution.
//
////////////////////////////////////////////////////////////
#pragma once
////////////////////////////////////////////////////////////
// Headers
////////////////////////////////////////////////////////////
#include <SFML/Config.hpp>
////////////////////////////////////////////////////////////
// Portable import / export macros
////////////////////////////////////////////////////////////
#if defined(SFML_NETWORK_EXPORTS)
#define SFML_NETWORK_API SFML_API_EXPORT
#else
#define SFML_NETWORK_API SFML_API_IMPORT
#endif

View File

@ -1,629 +0,0 @@
////////////////////////////////////////////////////////////
//
// SFML - Simple and Fast Multimedia Library
// Copyright (C) 2007-2025 Laurent Gomila (laurent@sfml-dev.org)
//
// This software is provided 'as-is', without any express or implied warranty.
// In no event will the authors be held liable for any damages arising from the use of this software.
//
// Permission is granted to anyone to use this software for any purpose,
// including commercial applications, and to alter it and redistribute it freely,
// subject to the following restrictions:
//
// 1. The origin of this software must not be misrepresented;
// you must not claim that you wrote the original software.
// If you use this software in a product, an acknowledgment
// in the product documentation would be appreciated but is not required.
//
// 2. Altered source versions must be plainly marked as such,
// and must not be misrepresented as being the original software.
//
// 3. This notice may not be removed or altered from any source distribution.
//
////////////////////////////////////////////////////////////
#pragma once
////////////////////////////////////////////////////////////
// Headers
////////////////////////////////////////////////////////////
#include <SFML/Network/Export.hpp>
#include <SFML/Network/TcpSocket.hpp>
#include <SFML/System/Time.hpp>
#include <filesystem>
#include <string>
#include <vector>
namespace sf
{
class IpAddress;
////////////////////////////////////////////////////////////
/// \brief A FTP client
///
////////////////////////////////////////////////////////////
class SFML_NETWORK_API Ftp
{
public:
////////////////////////////////////////////////////////////
/// \brief Enumeration of transfer modes
///
////////////////////////////////////////////////////////////
enum class TransferMode
{
Binary, //!< Binary mode (file is transferred as a sequence of bytes)
Ascii, //!< Text mode using ASCII encoding
Ebcdic //!< Text mode using EBCDIC encoding
};
////////////////////////////////////////////////////////////
/// \brief FTP response
///
////////////////////////////////////////////////////////////
class SFML_NETWORK_API Response
{
public:
////////////////////////////////////////////////////////////
/// \brief Status codes possibly returned by a FTP response
///
////////////////////////////////////////////////////////////
enum class Status
{
// 1xx: the requested action is being initiated,
// expect another reply before proceeding with a new command
RestartMarkerReply = 110, //!< Restart marker reply
ServiceReadySoon = 120, //!< Service ready in N minutes
DataConnectionAlreadyOpened = 125, //!< Data connection already opened, transfer starting
OpeningDataConnection = 150, //!< File status ok, about to open data connection
// 2xx: the requested action has been successfully completed
Ok = 200, //!< Command ok
PointlessCommand = 202, //!< Command not implemented
SystemStatus = 211, //!< System status, or system help reply
DirectoryStatus = 212, //!< Directory status
FileStatus = 213, //!< File status
HelpMessage = 214, //!< Help message
SystemType = 215, //!< NAME system type, where NAME is an official system name from the list in the Assigned Numbers document
ServiceReady = 220, //!< Service ready for new user
ClosingConnection = 221, //!< Service closing control connection
DataConnectionOpened = 225, //!< Data connection open, no transfer in progress
ClosingDataConnection = 226, //!< Closing data connection, requested file action successful
EnteringPassiveMode = 227, //!< Entering passive mode
LoggedIn = 230, //!< User logged in, proceed. Logged out if appropriate
FileActionOk = 250, //!< Requested file action ok
DirectoryOk = 257, //!< PATHNAME created
// 3xx: the command has been accepted, but the requested action
// is dormant, pending receipt of further information
NeedPassword = 331, //!< User name ok, need password
NeedAccountToLogIn = 332, //!< Need account for login
NeedInformation = 350, //!< Requested file action pending further information
// 4xx: the command was not accepted and the requested action did not take place,
// but the error condition is temporary and the action may be requested again
ServiceUnavailable = 421, //!< Service not available, closing control connection
DataConnectionUnavailable = 425, //!< Can't open data connection
TransferAborted = 426, //!< Connection closed, transfer aborted
FileActionAborted = 450, //!< Requested file action not taken
LocalError = 451, //!< Requested action aborted, local error in processing
InsufficientStorageSpace = 452, //!< Requested action not taken; insufficient storage space in system, file unavailable
// 5xx: the command was not accepted and
// the requested action did not take place
CommandUnknown = 500, //!< Syntax error, command unrecognized
ParametersUnknown = 501, //!< Syntax error in parameters or arguments
CommandNotImplemented = 502, //!< Command not implemented
BadCommandSequence = 503, //!< Bad sequence of commands
ParameterNotImplemented = 504, //!< Command not implemented for that parameter
NotLoggedIn = 530, //!< Not logged in
NeedAccountToStore = 532, //!< Need account for storing files
FileUnavailable = 550, //!< Requested action not taken, file unavailable
PageTypeUnknown = 551, //!< Requested action aborted, page type unknown
NotEnoughMemory = 552, //!< Requested file action aborted, exceeded storage allocation
FilenameNotAllowed = 553, //!< Requested action not taken, file name not allowed
// 10xx: SFML custom codes
InvalidResponse = 1000, //!< Not part of the FTP standard, generated by SFML when a received response cannot be parsed
ConnectionFailed = 1001, //!< Not part of the FTP standard, generated by SFML when the low-level socket connection with the server fails
ConnectionClosed = 1002, //!< Not part of the FTP standard, generated by SFML when the low-level socket connection is unexpectedly closed
InvalidFile = 1003 //!< Not part of the FTP standard, generated by SFML when a local file cannot be read or written
};
////////////////////////////////////////////////////////////
/// \brief Default constructor
///
/// This constructor is used by the FTP client to build
/// the response.
///
/// \param code Response status code
/// \param message Response message
///
////////////////////////////////////////////////////////////
explicit Response(Status code = Status::InvalidResponse, std::string message = "");
////////////////////////////////////////////////////////////
/// \brief Check if the status code means a success
///
/// This function is defined for convenience, it is
/// equivalent to testing if the status code is < 400.
///
/// \return `true` if the status is a success, `false` if it is a failure
///
////////////////////////////////////////////////////////////
[[nodiscard]] bool isOk() const;
////////////////////////////////////////////////////////////
/// \brief Get the status code of the response
///
/// \return Status code
///
////////////////////////////////////////////////////////////
[[nodiscard]] Status getStatus() const;
////////////////////////////////////////////////////////////
/// \brief Get the full message contained in the response
///
/// \return The response message
///
////////////////////////////////////////////////////////////
[[nodiscard]] const std::string& getMessage() const;
private:
////////////////////////////////////////////////////////////
// Member data
////////////////////////////////////////////////////////////
Status m_status; //!< Status code returned from the server
std::string m_message; //!< Last message received from the server
};
////////////////////////////////////////////////////////////
/// \brief Specialization of FTP response returning a directory
///
////////////////////////////////////////////////////////////
class SFML_NETWORK_API DirectoryResponse : public Response
{
public:
////////////////////////////////////////////////////////////
/// \brief Default constructor
///
/// \param response Source response
///
////////////////////////////////////////////////////////////
DirectoryResponse(const Response& response);
////////////////////////////////////////////////////////////
/// \brief Get the directory returned in the response
///
/// \return Directory name
///
////////////////////////////////////////////////////////////
[[nodiscard]] const std::filesystem::path& getDirectory() const;
private:
////////////////////////////////////////////////////////////
// Member data
////////////////////////////////////////////////////////////
std::filesystem::path m_directory; //!< Directory extracted from the response message
};
////////////////////////////////////////////////////////////
/// \brief Specialization of FTP response returning a
/// file name listing
////////////////////////////////////////////////////////////
class SFML_NETWORK_API ListingResponse : public Response
{
public:
////////////////////////////////////////////////////////////
/// \brief Default constructor
///
/// \param response Source response
/// \param data Data containing the raw listing
///
////////////////////////////////////////////////////////////
ListingResponse(const Response& response, const std::string& data);
////////////////////////////////////////////////////////////
/// \brief Return the array of directory/file names
///
/// \return Array containing the requested listing
///
////////////////////////////////////////////////////////////
[[nodiscard]] const std::vector<std::string>& getListing() const;
private:
////////////////////////////////////////////////////////////
// Member data
////////////////////////////////////////////////////////////
std::vector<std::string> m_listing; //!< Directory/file names extracted from the data
};
////////////////////////////////////////////////////////////
/// \brief Default constructor
///
////////////////////////////////////////////////////////////
Ftp() = default;
////////////////////////////////////////////////////////////
/// \brief Destructor
///
/// Automatically closes the connection with the server if
/// it is still opened.
///
////////////////////////////////////////////////////////////
~Ftp();
////////////////////////////////////////////////////////////
/// \brief Deleted copy constructor
///
////////////////////////////////////////////////////////////
Ftp(const Ftp&) = delete;
////////////////////////////////////////////////////////////
/// \brief Deleted copy assignment
///
////////////////////////////////////////////////////////////
Ftp& operator=(const Ftp&) = delete;
////////////////////////////////////////////////////////////
/// \brief Connect to the specified FTP server
///
/// The port has a default value of 21, which is the standard
/// port used by the FTP protocol. You shouldn't use a different
/// value, unless you really know what you do.
/// This function tries to connect to the server so it may take
/// a while to complete, especially if the server is not
/// reachable. To avoid blocking your application for too long,
/// you can use a timeout. The default value, `Time::Zero`, means that the
/// system timeout will be used (which is usually pretty long).
///
/// \param server Name or address of the FTP server to connect to
/// \param port Port used for the connection
/// \param timeout Maximum time to wait
///
/// \return Server response to the request
///
/// \see `disconnect`
///
////////////////////////////////////////////////////////////
[[nodiscard]] Response connect(IpAddress server, unsigned short port = 21, Time timeout = Time::Zero);
////////////////////////////////////////////////////////////
/// \brief Close the connection with the server
///
/// \return Server response to the request
///
/// \see `connect`
///
////////////////////////////////////////////////////////////
[[nodiscard]] Response disconnect();
////////////////////////////////////////////////////////////
/// \brief Log in using an anonymous account
///
/// Logging in is mandatory after connecting to the server.
/// Users that are not logged in cannot perform any operation.
///
/// \return Server response to the request
///
////////////////////////////////////////////////////////////
[[nodiscard]] Response login();
////////////////////////////////////////////////////////////
/// \brief Log in using a username and a password
///
/// Logging in is mandatory after connecting to the server.
/// Users that are not logged in cannot perform any operation.
///
/// \param name User name
/// \param password Password
///
/// \return Server response to the request
///
////////////////////////////////////////////////////////////
[[nodiscard]] Response login(const std::string& name, const std::string& password);
////////////////////////////////////////////////////////////
/// \brief Send a null command to keep the connection alive
///
/// This command is useful because the server may close the
/// connection automatically if no command is sent.
///
/// \return Server response to the request
///
////////////////////////////////////////////////////////////
[[nodiscard]] Response keepAlive();
////////////////////////////////////////////////////////////
/// \brief Get the current working directory
///
/// The working directory is the root path for subsequent
/// operations involving directories and/or filenames.
///
/// \return Server response to the request
///
/// \see `getDirectoryListing`, `changeDirectory`, `parentDirectory`
///
////////////////////////////////////////////////////////////
[[nodiscard]] DirectoryResponse getWorkingDirectory();
////////////////////////////////////////////////////////////
/// \brief Get the contents of the given directory
///
/// This function retrieves the sub-directories and files
/// contained in the given directory. It is not recursive.
/// The `directory` parameter is relative to the current
/// working directory.
///
/// \param directory Directory to list
///
/// \return Server response to the request
///
/// \see `getWorkingDirectory`, `changeDirectory`, `parentDirectory`
///
////////////////////////////////////////////////////////////
[[nodiscard]] ListingResponse getDirectoryListing(const std::string& directory = "");
////////////////////////////////////////////////////////////
/// \brief Change the current working directory
///
/// The new directory must be relative to the current one.
///
/// \param directory New working directory
///
/// \return Server response to the request
///
/// \see `getWorkingDirectory`, `getDirectoryListing`, `parentDirectory`
///
////////////////////////////////////////////////////////////
[[nodiscard]] Response changeDirectory(const std::string& directory);
////////////////////////////////////////////////////////////
/// \brief Go to the parent directory of the current one
///
/// \return Server response to the request
///
/// \see `getWorkingDirectory`, `getDirectoryListing`, `changeDirectory`
///
////////////////////////////////////////////////////////////
[[nodiscard]] Response parentDirectory();
////////////////////////////////////////////////////////////
/// \brief Create a new directory
///
/// The new directory is created as a child of the current
/// working directory.
///
/// \param name Name of the directory to create
///
/// \return Server response to the request
///
/// \see `deleteDirectory`
///
////////////////////////////////////////////////////////////
[[nodiscard]] Response createDirectory(const std::string& name);
////////////////////////////////////////////////////////////
/// \brief Remove an existing directory
///
/// The directory to remove must be relative to the
/// current working directory.
/// Use this function with caution, the directory will
/// be removed permanently!
///
/// \param name Name of the directory to remove
///
/// \return Server response to the request
///
/// \see `createDirectory`
///
////////////////////////////////////////////////////////////
[[nodiscard]] Response deleteDirectory(const std::string& name);
////////////////////////////////////////////////////////////
/// \brief Rename an existing file
///
/// The file names must be relative to the current working
/// directory.
///
/// \param file File to rename
/// \param newName New name of the file
///
/// \return Server response to the request
///
/// \see `deleteFile`
///
////////////////////////////////////////////////////////////
[[nodiscard]] Response renameFile(const std::filesystem::path& file, const std::filesystem::path& newName);
////////////////////////////////////////////////////////////
/// \brief Remove an existing file
///
/// The file name must be relative to the current working
/// directory.
/// Use this function with caution, the file will be
/// removed permanently!
///
/// \param name File to remove
///
/// \return Server response to the request
///
/// \see `renameFile`
///
////////////////////////////////////////////////////////////
[[nodiscard]] Response deleteFile(const std::filesystem::path& name);
////////////////////////////////////////////////////////////
/// \brief Download a file from the server
///
/// The file name of the distant file is relative to the
/// current working directory of the server, and the local
/// destination path is relative to the current directory
/// of your application.
/// If a file with the same file name as the distant file
/// already exists in the local destination path, it will
/// be overwritten.
///
/// \param remoteFile File name of the distant file to download
/// \param localPath The directory in which to put the file on the local computer
/// \param mode Transfer mode
///
/// \return Server response to the request
///
/// \see `upload`
///
////////////////////////////////////////////////////////////
[[nodiscard]] Response download(const std::filesystem::path& remoteFile,
const std::filesystem::path& localPath,
TransferMode mode = TransferMode::Binary);
////////////////////////////////////////////////////////////
/// \brief Upload a file to the server
///
/// The name of the local file is relative to the current
/// working directory of your application, and the
/// remote path is relative to the current directory of the
/// FTP server.
///
/// The append parameter controls whether the remote file is
/// appended to or overwritten if it already exists.
///
/// \param localFile Path of the local file to upload
/// \param remotePath The directory in which to put the file on the server
/// \param mode Transfer mode
/// \param append Pass `true` to append to or `false` to overwrite the remote file if it already exists
///
/// \return Server response to the request
///
/// \see `download`
///
////////////////////////////////////////////////////////////
[[nodiscard]] Response upload(const std::filesystem::path& localFile,
const std::filesystem::path& remotePath,
TransferMode mode = TransferMode::Binary,
bool append = false);
////////////////////////////////////////////////////////////
/// \brief Send a command to the FTP server
///
/// While the most often used commands are provided as member
/// functions in the `sf::Ftp` class, this method can be used
/// to send any FTP command to the server. If the command
/// requires one or more parameters, they can be specified
/// in `parameter`. If the server returns information, you
/// can extract it from the response using `Response::getMessage()`.
///
/// \param command Command to send
/// \param parameter Command parameter
///
/// \return Server response to the request
///
////////////////////////////////////////////////////////////
[[nodiscard]] Response sendCommand(const std::string& command, const std::string& parameter = "");
private:
////////////////////////////////////////////////////////////
/// \brief Receive a response from the server
///
/// This function must be called after each call to
/// `sendCommand` that expects a response.
///
/// \return Server response to the request
///
////////////////////////////////////////////////////////////
Response getResponse();
////////////////////////////////////////////////////////////
/// \brief Utility class for exchanging data with the server
/// on the data channel
///
////////////////////////////////////////////////////////////
class DataChannel;
friend class DataChannel;
////////////////////////////////////////////////////////////
// Member data
////////////////////////////////////////////////////////////
TcpSocket m_commandSocket; //!< Socket holding the control connection with the server
std::string m_receiveBuffer; //!< Received command data that is yet to be processed
};
} // namespace sf
////////////////////////////////////////////////////////////
/// \class sf::Ftp
/// \ingroup network
///
/// `sf::Ftp` is a very simple FTP client that allows you
/// to communicate with a FTP server. The FTP protocol allows
/// you to manipulate a remote file system (list files,
/// upload, download, create, remove, ...).
///
/// Using the FTP client consists of 4 parts:
/// \li Connecting to the FTP server
/// \li Logging in (either as a registered user or anonymously)
/// \li Sending commands to the server
/// \li Disconnecting (this part can be done implicitly by the destructor)
///
/// Every command returns a FTP response, which contains the
/// status code as well as a message from the server. Some
/// commands such as `getWorkingDirectory()` and `getDirectoryListing()`
/// return additional data, and use a class derived from
/// `sf::Ftp::Response` to provide this data. The most often used
/// commands are directly provided as member functions, but it is
/// also possible to use specific commands with the `sendCommand()` function.
///
/// Note that response statuses >= 1000 are not part of the FTP standard,
/// they are generated by SFML when an internal error occurs.
///
/// All commands, especially upload and download, may take some
/// time to complete. This is important to know if you don't want
/// to block your application while the server is completing
/// the task.
///
/// Usage example:
/// \code
/// // Create a new FTP client
/// sf::Ftp ftp;
///
/// // Connect to the server
/// sf::Ftp::Response response = ftp.connect("ftp://ftp.myserver.com");
/// if (response.isOk())
/// std::cout << "Connected" << std::endl;
///
/// // Log in
/// response = ftp.login("laurent", "dF6Zm89D");
/// if (response.isOk())
/// std::cout << "Logged in" << std::endl;
///
/// // Print the working directory
/// sf::Ftp::DirectoryResponse directory = ftp.getWorkingDirectory();
/// if (directory.isOk())
/// std::cout << "Working directory: " << directory.getDirectory() << std::endl;
///
/// // Create a new directory
/// response = ftp.createDirectory("files");
/// if (response.isOk())
/// std::cout << "Created new directory" << std::endl;
///
/// // Upload a file to this new directory
/// response = ftp.upload("local-path/file.txt", "files", sf::Ftp::TransferMode::Ascii);
/// if (response.isOk())
/// std::cout << "File uploaded" << std::endl;
///
/// // Send specific commands (here: FEAT to list supported FTP features)
/// response = ftp.sendCommand("FEAT");
/// if (response.isOk())
/// std::cout << "Feature list:\n" << response.getMessage() << std::endl;
///
/// // Disconnect from the server (optional)
/// ftp.disconnect();
/// \endcode
///
////////////////////////////////////////////////////////////

View File

@ -1,480 +0,0 @@
////////////////////////////////////////////////////////////
//
// SFML - Simple and Fast Multimedia Library
// Copyright (C) 2007-2025 Laurent Gomila (laurent@sfml-dev.org)
//
// This software is provided 'as-is', without any express or implied warranty.
// In no event will the authors be held liable for any damages arising from the use of this software.
//
// Permission is granted to anyone to use this software for any purpose,
// including commercial applications, and to alter it and redistribute it freely,
// subject to the following restrictions:
//
// 1. The origin of this software must not be misrepresented;
// you must not claim that you wrote the original software.
// If you use this software in a product, an acknowledgment
// in the product documentation would be appreciated but is not required.
//
// 2. Altered source versions must be plainly marked as such,
// and must not be misrepresented as being the original software.
//
// 3. This notice may not be removed or altered from any source distribution.
//
////////////////////////////////////////////////////////////
#pragma once
////////////////////////////////////////////////////////////
// Headers
////////////////////////////////////////////////////////////
#include <SFML/Network/Export.hpp>
#include <SFML/Network/IpAddress.hpp>
#include <SFML/Network/TcpSocket.hpp>
#include <SFML/System/Time.hpp>
#include <iosfwd>
#include <map>
#include <optional>
#include <string>
namespace sf
{
////////////////////////////////////////////////////////////
/// \brief A HTTP client
///
////////////////////////////////////////////////////////////
class SFML_NETWORK_API Http
{
public:
////////////////////////////////////////////////////////////
/// \brief HTTP request
///
////////////////////////////////////////////////////////////
class SFML_NETWORK_API Request
{
public:
////////////////////////////////////////////////////////////
/// \brief Enumerate the available HTTP methods for a request
///
////////////////////////////////////////////////////////////
enum class Method
{
Get, //!< Request in get mode, standard method to retrieve a page
Post, //!< Request in post mode, usually to send data to a page
Head, //!< Request a page's header only
Put, //!< Request in put mode, useful for a REST API
Delete //!< Request in delete mode, useful for a REST API
};
////////////////////////////////////////////////////////////
/// \brief Default constructor
///
/// This constructor creates a GET request, with the root
/// URI ("/") and an empty body.
///
/// \param uri Target URI
/// \param method Method to use for the request
/// \param body Content of the request's body
///
////////////////////////////////////////////////////////////
Request(const std::string& uri = "/", Method method = Method::Get, const std::string& body = "");
////////////////////////////////////////////////////////////
/// \brief Set the value of a field
///
/// The field is created if it doesn't exist. The name of
/// the field is case-insensitive.
/// By default, a request doesn't contain any field (but the
/// mandatory fields are added later by the HTTP client when
/// sending the request).
///
/// \param field Name of the field to set
/// \param value Value of the field
///
////////////////////////////////////////////////////////////
void setField(const std::string& field, const std::string& value);
////////////////////////////////////////////////////////////
/// \brief Set the request method
///
/// See the Method enumeration for a complete list of all
/// the available methods.
/// The method is `Http::Request::Method::Get` by default.
///
/// \param method Method to use for the request
///
////////////////////////////////////////////////////////////
void setMethod(Method method);
////////////////////////////////////////////////////////////
/// \brief Set the requested URI
///
/// The URI is the resource (usually a web page or a file)
/// that you want to get or post.
/// The URI is "/" (the root page) by default.
///
/// \param uri URI to request, relative to the host
///
////////////////////////////////////////////////////////////
void setUri(const std::string& uri);
////////////////////////////////////////////////////////////
/// \brief Set the HTTP version for the request
///
/// The HTTP version is 1.0 by default.
///
/// \param major Major HTTP version number
/// \param minor Minor HTTP version number
///
////////////////////////////////////////////////////////////
void setHttpVersion(unsigned int major, unsigned int minor);
////////////////////////////////////////////////////////////
/// \brief Set the body of the request
///
/// The body of a request is optional and only makes sense
/// for POST requests. It is ignored for all other methods.
/// The body is empty by default.
///
/// \param body Content of the body
///
////////////////////////////////////////////////////////////
void setBody(const std::string& body);
private:
friend class Http;
////////////////////////////////////////////////////////////
/// \brief Prepare the final request to send to the server
///
/// This is used internally by Http before sending the
/// request to the web server.
///
/// \return String containing the request, ready to be sent
///
////////////////////////////////////////////////////////////
[[nodiscard]] std::string prepare() const;
////////////////////////////////////////////////////////////
/// \brief Check if the request defines a field
///
/// This function uses case-insensitive comparisons.
///
/// \param field Name of the field to test
///
/// \return `true` if the field exists, `false` otherwise
///
////////////////////////////////////////////////////////////
[[nodiscard]] bool hasField(const std::string& field) const;
////////////////////////////////////////////////////////////
// Types
////////////////////////////////////////////////////////////
using FieldTable = std::map<std::string, std::string>; // Use an ordered map for predictable payloads
////////////////////////////////////////////////////////////
// Member data
////////////////////////////////////////////////////////////
FieldTable m_fields; //!< Fields of the header associated to their value
Method m_method; //!< Method to use for the request
std::string m_uri; //!< Target URI of the request
unsigned int m_majorVersion{1}; //!< Major HTTP version
unsigned int m_minorVersion{}; //!< Minor HTTP version
std::string m_body; //!< Body of the request
};
////////////////////////////////////////////////////////////
/// \brief HTTP response
///
////////////////////////////////////////////////////////////
class SFML_NETWORK_API Response
{
public:
////////////////////////////////////////////////////////////
/// \brief Enumerate all the valid status codes for a response
///
////////////////////////////////////////////////////////////
enum class Status
{
// 2xx: success
Ok = 200, //!< Most common code returned when operation was successful
Created = 201, //!< The resource has successfully been created
Accepted = 202, //!< The request has been accepted, but will be processed later by the server
NoContent = 204, //!< The server didn't send any data in return
ResetContent = 205, //!< The server informs the client that it should clear the view (form) that caused the request to be sent
PartialContent = 206, //!< The server has sent a part of the resource, as a response to a partial GET request
// 3xx: redirection
MultipleChoices = 300, //!< The requested page can be accessed from several locations
MovedPermanently = 301, //!< The requested page has permanently moved to a new location
MovedTemporarily = 302, //!< The requested page has temporarily moved to a new location
NotModified = 304, //!< For conditional requests, means the requested page hasn't changed and doesn't need to be refreshed
// 4xx: client error
BadRequest = 400, //!< The server couldn't understand the request (syntax error)
Unauthorized = 401, //!< The requested page needs an authentication to be accessed
Forbidden = 403, //!< The requested page cannot be accessed at all, even with authentication
NotFound = 404, //!< The requested page doesn't exist
RangeNotSatisfiable = 407, //!< The server can't satisfy the partial GET request (with a "Range" header field)
// 5xx: server error
InternalServerError = 500, //!< The server encountered an unexpected error
NotImplemented = 501, //!< The server doesn't implement a requested feature
BadGateway = 502, //!< The gateway server has received an error from the source server
ServiceNotAvailable = 503, //!< The server is temporarily unavailable (overloaded, in maintenance, ...)
GatewayTimeout = 504, //!< The gateway server couldn't receive a response from the source server
VersionNotSupported = 505, //!< The server doesn't support the requested HTTP version
// 10xx: SFML custom codes
InvalidResponse = 1000, //!< Response is not a valid HTTP one
ConnectionFailed = 1001 //!< Connection with server failed
};
////////////////////////////////////////////////////////////
/// \brief Get the value of a field
///
/// If the field `field` is not found in the response header,
/// the empty string is returned. This function uses
/// case-insensitive comparisons.
///
/// \param field Name of the field to get
///
/// \return Value of the field, or empty string if not found
///
////////////////////////////////////////////////////////////
[[nodiscard]] const std::string& getField(const std::string& field) const;
////////////////////////////////////////////////////////////
/// \brief Get the response status code
///
/// The status code should be the first thing to be checked
/// after receiving a response, it defines whether it is a
/// success, a failure or anything else (see the Status
/// enumeration).
///
/// \return Status code of the response
///
////////////////////////////////////////////////////////////
[[nodiscard]] Status getStatus() const;
////////////////////////////////////////////////////////////
/// \brief Get the major HTTP version number of the response
///
/// \return Major HTTP version number
///
/// \see `getMinorHttpVersion`
///
////////////////////////////////////////////////////////////
[[nodiscard]] unsigned int getMajorHttpVersion() const;
////////////////////////////////////////////////////////////
/// \brief Get the minor HTTP version number of the response
///
/// \return Minor HTTP version number
///
/// \see `getMajorHttpVersion`
///
////////////////////////////////////////////////////////////
[[nodiscard]] unsigned int getMinorHttpVersion() const;
////////////////////////////////////////////////////////////
/// \brief Get the body of the response
///
/// The body of a response may contain:
/// \li the requested page (for GET requests)
/// \li a response from the server (for POST requests)
/// \li nothing (for HEAD requests)
/// \li an error message (in case of an error)
///
/// \return The response body
///
////////////////////////////////////////////////////////////
[[nodiscard]] const std::string& getBody() const;
private:
friend class Http;
////////////////////////////////////////////////////////////
/// \brief Construct the header from a response string
///
/// This function is used by `Http` to build the response
/// of a request.
///
/// \param data Content of the response to parse
///
////////////////////////////////////////////////////////////
void parse(const std::string& data);
////////////////////////////////////////////////////////////
/// \brief Read values passed in the answer header
///
/// This function is used by `Http` to extract values passed
/// in the response.
///
/// \param in String stream containing the header values
///
////////////////////////////////////////////////////////////
void parseFields(std::istream& in);
////////////////////////////////////////////////////////////
// Types
////////////////////////////////////////////////////////////
using FieldTable = std::map<std::string, std::string>; // Use an ordered map for predictable payloads
////////////////////////////////////////////////////////////
// Member data
////////////////////////////////////////////////////////////
FieldTable m_fields; //!< Fields of the header
Status m_status{Status::ConnectionFailed}; //!< Status code
unsigned int m_majorVersion{}; //!< Major HTTP version
unsigned int m_minorVersion{}; //!< Minor HTTP version
std::string m_body; //!< Body of the response
};
////////////////////////////////////////////////////////////
/// \brief Default constructor
///
////////////////////////////////////////////////////////////
Http() = default;
////////////////////////////////////////////////////////////
/// \brief Construct the HTTP client with the target host
///
/// This is equivalent to calling `setHost(host, port)`.
/// The port has a default value of 0, which means that the
/// HTTP client will use the right port according to the
/// protocol used (80 for HTTP). You should leave it like
/// this unless you really need a port other than the
/// standard one, or use an unknown protocol.
///
/// \param host Web server to connect to
/// \param port Port to use for connection
///
////////////////////////////////////////////////////////////
Http(const std::string& host, unsigned short port = 0);
////////////////////////////////////////////////////////////
/// \brief Deleted copy constructor
///
////////////////////////////////////////////////////////////
Http(const Http&) = delete;
////////////////////////////////////////////////////////////
/// \brief Deleted copy assignment
///
////////////////////////////////////////////////////////////
Http& operator=(const Http&) = delete;
////////////////////////////////////////////////////////////
/// \brief Set the target host
///
/// This function just stores the host address and port, it
/// doesn't actually connect to it until you send a request.
/// The port has a default value of 0, which means that the
/// HTTP client will use the right port according to the
/// protocol used (80 for HTTP). You should leave it like
/// this unless you really need a port other than the
/// standard one, or use an unknown protocol.
///
/// \param host Web server to connect to
/// \param port Port to use for connection
///
////////////////////////////////////////////////////////////
void setHost(const std::string& host, unsigned short port = 0);
////////////////////////////////////////////////////////////
/// \brief Send a HTTP request and return the server's response.
///
/// You must have a valid host before sending a request (see `setHost`).
/// Any missing mandatory header field in the request will be added
/// with an appropriate value.
/// Warning: this function waits for the server's response and may
/// not return instantly; use a thread if you don't want to block your
/// application, or use a timeout to limit the time to wait. A value
/// of `Time::Zero` means that the client will use the system default timeout
/// (which is usually pretty long).
///
/// \param request Request to send
/// \param timeout Maximum time to wait
///
/// \return Server's response
///
////////////////////////////////////////////////////////////
[[nodiscard]] Response sendRequest(const Request& request, Time timeout = Time::Zero);
private:
////////////////////////////////////////////////////////////
// Member data
////////////////////////////////////////////////////////////
TcpSocket m_connection; //!< Connection to the host
std::optional<IpAddress> m_host; //!< Web host address
std::string m_hostName; //!< Web host name
unsigned short m_port{}; //!< Port used for connection with host
};
} // namespace sf
////////////////////////////////////////////////////////////
/// \class sf::Http
/// \ingroup network
///
/// `sf::Http` is a very simple HTTP client that allows you
/// to communicate with a web server. You can retrieve
/// web pages, send data to an interactive resource,
/// download a remote file, etc. The HTTPS protocol is
/// not supported.
///
/// The HTTP client is split into 3 classes:
/// \li `sf::Http::Request`
/// \li `sf::Http::Response`
/// \li `sf::Http`
///
/// `sf::Http::Request` builds the request that will be
/// sent to the server. A request is made of:
/// \li a method (what you want to do)
/// \li a target URI (usually the name of the web page or file)
/// \li one or more header fields (options that you can pass to the server)
/// \li an optional body (for POST requests)
///
/// `sf::Http::Response` parse the response from the web server
/// and provides getters to read them. The response contains:
/// \li a status code
/// \li header fields (that may be answers to the ones that you requested)
/// \li a body, which contains the contents of the requested resource
///
/// `sf::Http` provides a simple function, SendRequest, to send a
/// `sf::Http::Request` and return the corresponding `sf::Http::Response`
/// from the server.
///
/// Usage example:
/// \code
/// // Create a new HTTP client
/// sf::Http http;
///
/// // We'll work on http://www.sfml-dev.org
/// http.setHost("http://www.sfml-dev.org");
///
/// // Prepare a request to get the 'features.php' page
/// sf::Http::Request request("features.php");
///
/// // Send the request
/// sf::Http::Response response = http.sendRequest(request);
///
/// // Check the status code and display the result
/// sf::Http::Response::Status status = response.getStatus();
/// if (status == sf::Http::Response::Status::Ok)
/// {
/// std::cout << response.getBody() << std::endl;
/// }
/// else
/// {
/// std::cout << "Error " << status << std::endl;
/// }
/// \endcode
///
////////////////////////////////////////////////////////////

View File

@ -1,297 +0,0 @@
////////////////////////////////////////////////////////////
//
// SFML - Simple and Fast Multimedia Library
// Copyright (C) 2007-2025 Laurent Gomila (laurent@sfml-dev.org)
//
// This software is provided 'as-is', without any express or implied warranty.
// In no event will the authors be held liable for any damages arising from the use of this software.
//
// Permission is granted to anyone to use this software for any purpose,
// including commercial applications, and to alter it and redistribute it freely,
// subject to the following restrictions:
//
// 1. The origin of this software must not be misrepresented;
// you must not claim that you wrote the original software.
// If you use this software in a product, an acknowledgment
// in the product documentation would be appreciated but is not required.
//
// 2. Altered source versions must be plainly marked as such,
// and must not be misrepresented as being the original software.
//
// 3. This notice may not be removed or altered from any source distribution.
//
////////////////////////////////////////////////////////////
#pragma once
////////////////////////////////////////////////////////////
// Headers
////////////////////////////////////////////////////////////
#include <SFML/Network/Export.hpp>
#include <SFML/System/Time.hpp>
#include <iosfwd>
#include <optional>
#include <string>
#include <string_view>
#include <cstdint>
namespace sf
{
////////////////////////////////////////////////////////////
/// \brief Encapsulate an IPv4 network address
///
////////////////////////////////////////////////////////////
class SFML_NETWORK_API IpAddress
{
public:
////////////////////////////////////////////////////////////
/// \brief Construct the address from a null-terminated string view
///
/// Here \a address can be either a decimal address
/// (ex: "192.168.1.56") or a network name (ex: "localhost").
///
/// \param address IP address or network name
///
/// \return Address if provided argument was valid, otherwise `std::nullopt`
///
////////////////////////////////////////////////////////////
[[nodiscard]] static std::optional<IpAddress> resolve(std::string_view address);
////////////////////////////////////////////////////////////
/// \brief Construct the address from 4 bytes
///
/// Calling `IpAddress(a, b, c, d)` is equivalent to calling
/// `IpAddress::resolve("a.b.c.d")`, but safer as it doesn't
/// have to parse a string to get the address components.
///
/// \param byte0 First byte of the address
/// \param byte1 Second byte of the address
/// \param byte2 Third byte of the address
/// \param byte3 Fourth byte of the address
///
////////////////////////////////////////////////////////////
IpAddress(std::uint8_t byte0, std::uint8_t byte1, std::uint8_t byte2, std::uint8_t byte3);
////////////////////////////////////////////////////////////
/// \brief Construct the address from a 32-bits integer
///
/// This constructor uses the internal representation of
/// the address directly. It should be used for optimization
/// purposes, and only if you got that representation from
/// `IpAddress::toInteger()`.
///
/// \param address 4 bytes of the address packed into a 32-bits integer
///
/// \see `toInteger`
///
////////////////////////////////////////////////////////////
explicit IpAddress(std::uint32_t address);
////////////////////////////////////////////////////////////
/// \brief Get a string representation of the address
///
/// The returned string is the decimal representation of the
/// IP address (like "192.168.1.56"), even if it was constructed
/// from a host name.
///
/// \return String representation of the address
///
/// \see `toInteger`
///
////////////////////////////////////////////////////////////
[[nodiscard]] std::string toString() const;
////////////////////////////////////////////////////////////
/// \brief Get an integer representation of the address
///
/// The returned number is the internal representation of the
/// address, and should be used for optimization purposes only
/// (like sending the address through a socket).
/// The integer produced by this function can then be converted
/// back to a `sf::IpAddress` with the proper constructor.
///
/// \return 32-bits unsigned integer representation of the address
///
/// \see `toString`
///
////////////////////////////////////////////////////////////
[[nodiscard]] std::uint32_t toInteger() const;
////////////////////////////////////////////////////////////
/// \brief Get the computer's local address
///
/// The local address is the address of the computer from the
/// LAN point of view, i.e. something like 192.168.1.56. It is
/// meaningful only for communications over the local network.
/// Unlike getPublicAddress, this function is fast and may be
/// used safely anywhere.
///
/// \return Local IP address of the computer on success, `std::nullopt` otherwise
///
/// \see `getPublicAddress`
///
////////////////////////////////////////////////////////////
[[nodiscard]] static std::optional<IpAddress> getLocalAddress();
////////////////////////////////////////////////////////////
/// \brief Get the computer's public address
///
/// The public address is the address of the computer from the
/// internet point of view, i.e. something like 89.54.1.169.
/// It is necessary for communications over the world wide web.
/// The only way to get a public address is to ask it to a
/// distant website; as a consequence, this function depends on
/// both your network connection and the server, and may be
/// very slow. You should use it as few as possible. Because
/// this function depends on the network connection and on a distant
/// server, you may use a time limit if you don't want your program
/// to be possibly stuck waiting in case there is a problem; this
/// limit is deactivated by default.
///
/// \param timeout Maximum time to wait
///
/// \return Public IP address of the computer on success, `std::nullopt` otherwise
///
/// \see `getLocalAddress`
///
////////////////////////////////////////////////////////////
[[nodiscard]] static std::optional<IpAddress> getPublicAddress(Time timeout = Time::Zero);
////////////////////////////////////////////////////////////
// Static member data
////////////////////////////////////////////////////////////
// NOLINTBEGIN(readability-identifier-naming)
static const IpAddress Any; //!< Value representing any address (0.0.0.0)
static const IpAddress LocalHost; //!< The "localhost" address (for connecting a computer to itself locally)
static const IpAddress Broadcast; //!< The "broadcast" address (for sending UDP messages to everyone on a local network)
// NOLINTEND(readability-identifier-naming)
private:
friend SFML_NETWORK_API bool operator<(IpAddress left, IpAddress right);
////////////////////////////////////////////////////////////
// Member data
////////////////////////////////////////////////////////////
std::uint32_t m_address; //!< Address stored as an unsigned 32 bit integer
};
////////////////////////////////////////////////////////////
/// \brief Overload of `operator==` to compare two IP addresses
///
/// \param left Left operand (a IP address)
/// \param right Right operand (a IP address)
///
/// \return `true` if both addresses are equal
///
////////////////////////////////////////////////////////////
[[nodiscard]] SFML_NETWORK_API bool operator==(IpAddress left, IpAddress right);
////////////////////////////////////////////////////////////
/// \brief Overload of `operator!=` to compare two IP addresses
///
/// \param left Left operand (a IP address)
/// \param right Right operand (a IP address)
///
/// \return `true` if both addresses are different
///
////////////////////////////////////////////////////////////
[[nodiscard]] SFML_NETWORK_API bool operator!=(IpAddress left, IpAddress right);
////////////////////////////////////////////////////////////
/// \brief Overload of `operator<` to compare two IP addresses
///
/// \param left Left operand (a IP address)
/// \param right Right operand (a IP address)
///
/// \return `true` if `left` is lesser than `right`
///
////////////////////////////////////////////////////////////
[[nodiscard]] SFML_NETWORK_API bool operator<(IpAddress left, IpAddress right);
////////////////////////////////////////////////////////////
/// \brief Overload of `operator>` to compare two IP addresses
///
/// \param left Left operand (a IP address)
/// \param right Right operand (a IP address)
///
/// \return `true` if `left` is greater than `right`
///
////////////////////////////////////////////////////////////
[[nodiscard]] SFML_NETWORK_API bool operator>(IpAddress left, IpAddress right);
////////////////////////////////////////////////////////////
/// \brief Overload of `operator<=` to compare two IP addresses
///
/// \param left Left operand (a IP address)
/// \param right Right operand (a IP address)
///
/// \return `true` if \a left is lesser or equal than \a right
///
////////////////////////////////////////////////////////////
[[nodiscard]] SFML_NETWORK_API bool operator<=(IpAddress left, IpAddress right);
////////////////////////////////////////////////////////////
/// \brief Overload of `operator>=` to compare two IP addresses
///
/// \param left Left operand (a IP address)
/// \param right Right operand (a IP address)
///
/// \return `true` if `left` is greater or equal than `right`
///
////////////////////////////////////////////////////////////
[[nodiscard]] SFML_NETWORK_API bool operator>=(IpAddress left, IpAddress right);
////////////////////////////////////////////////////////////
/// \brief Overload of `operator>>` to extract an IP address from an input stream
///
/// \param stream Input stream
/// \param address IP address to extract
///
/// \return Reference to the input stream
///
////////////////////////////////////////////////////////////
SFML_NETWORK_API std::istream& operator>>(std::istream& stream, std::optional<IpAddress>& address);
////////////////////////////////////////////////////////////
/// \brief Overload of `operator<<` to print an IP address to an output stream
///
/// \param stream Output stream
/// \param address IP address to print
///
/// \return Reference to the output stream
///
////////////////////////////////////////////////////////////
SFML_NETWORK_API std::ostream& operator<<(std::ostream& stream, IpAddress address);
} // namespace sf
////////////////////////////////////////////////////////////
/// \class sf::IpAddress
/// \ingroup network
///
/// `sf::IpAddress` is a utility class for manipulating network
/// addresses. It provides a set a implicit constructors and
/// conversion functions to easily build or transform an IP
/// address from/to various representations.
///
/// Usage example:
/// \code
/// auto a2 = sf::IpAddress::resolve("127.0.0.1"); // the local host address
/// auto a3 = sf::IpAddress::Broadcast; // the broadcast address
/// sf::IpAddress a4(192, 168, 1, 56); // a local address
/// auto a5 = sf::IpAddress::resolve("my_computer"); // a local address created from a network name
/// auto a6 = sf::IpAddress::resolve("89.54.1.169"); // a distant address
/// auto a7 = sf::IpAddress::resolve("www.google.com"); // a distant address created from a network name
/// auto a8 = sf::IpAddress::getLocalAddress(); // my address on the local network
/// auto a9 = sf::IpAddress::getPublicAddress(); // my address on the internet
/// \endcode
///
/// Note that `sf::IpAddress` currently doesn't support IPv6
/// nor other types of network addresses.
///
////////////////////////////////////////////////////////////

View File

@ -1,548 +0,0 @@
////////////////////////////////////////////////////////////
//
// SFML - Simple and Fast Multimedia Library
// Copyright (C) 2007-2025 Laurent Gomila (laurent@sfml-dev.org)
//
// This software is provided 'as-is', without any express or implied warranty.
// In no event will the authors be held liable for any damages arising from the use of this software.
//
// Permission is granted to anyone to use this software for any purpose,
// including commercial applications, and to alter it and redistribute it freely,
// subject to the following restrictions:
//
// 1. The origin of this software must not be misrepresented;
// you must not claim that you wrote the original software.
// If you use this software in a product, an acknowledgment
// in the product documentation would be appreciated but is not required.
//
// 2. Altered source versions must be plainly marked as such,
// and must not be misrepresented as being the original software.
//
// 3. This notice may not be removed or altered from any source distribution.
//
////////////////////////////////////////////////////////////
#pragma once
////////////////////////////////////////////////////////////
// Headers
////////////////////////////////////////////////////////////
#include <SFML/Network/Export.hpp>
#include <string>
#include <vector>
#include <cstddef>
#include <cstdint>
namespace sf
{
class String;
////////////////////////////////////////////////////////////
/// \brief Utility class to build blocks of data to transfer
/// over the network
///
////////////////////////////////////////////////////////////
class SFML_NETWORK_API Packet
{
public:
////////////////////////////////////////////////////////////
/// \brief Default constructor
///
/// Creates an empty packet.
///
////////////////////////////////////////////////////////////
Packet() = default;
////////////////////////////////////////////////////////////
/// \brief Virtual destructor
///
////////////////////////////////////////////////////////////
virtual ~Packet() = default;
////////////////////////////////////////////////////////////
/// \brief Copy constructor
///
////////////////////////////////////////////////////////////
Packet(const Packet&) = default;
////////////////////////////////////////////////////////////
/// \brief Copy assignment
///
////////////////////////////////////////////////////////////
Packet& operator=(const Packet&) = default;
////////////////////////////////////////////////////////////
/// \brief Move constructor
///
////////////////////////////////////////////////////////////
Packet(Packet&&) noexcept = default;
////////////////////////////////////////////////////////////
/// \brief Move assignment
///
////////////////////////////////////////////////////////////
Packet& operator=(Packet&&) noexcept = default;
////////////////////////////////////////////////////////////
/// \brief Append data to the end of the packet
///
/// \param data Pointer to the sequence of bytes to append
/// \param sizeInBytes Number of bytes to append
///
/// \see `clear`
/// \see `getReadPosition`
///
////////////////////////////////////////////////////////////
void append(const void* data, std::size_t sizeInBytes);
////////////////////////////////////////////////////////////
/// \brief Get the current reading position in the packet
///
/// The next read operation will read data from this position
///
/// \return The byte offset of the current read position
///
/// \see `append`
///
////////////////////////////////////////////////////////////
[[nodiscard]] std::size_t getReadPosition() const;
////////////////////////////////////////////////////////////
/// \brief Clear the packet
///
/// After calling Clear, the packet is empty.
///
/// \see `append`
///
////////////////////////////////////////////////////////////
void clear();
////////////////////////////////////////////////////////////
/// \brief Get a pointer to the data contained in the packet
///
/// Warning: the returned pointer may become invalid after
/// you append data to the packet, therefore it should never
/// be stored.
/// The return pointer is a `nullptr` if the packet is empty.
///
/// \return Pointer to the data
///
/// \see `getDataSize`
///
////////////////////////////////////////////////////////////
[[nodiscard]] const void* getData() const;
////////////////////////////////////////////////////////////
/// \brief Get the size of the data contained in the packet
///
/// This function returns the number of bytes pointed to by
/// what `getData` returns.
///
/// \return Data size, in bytes
///
/// \see `getData`
///
////////////////////////////////////////////////////////////
[[nodiscard]] std::size_t getDataSize() const;
////////////////////////////////////////////////////////////
/// \brief Tell if the reading position has reached the
/// end of the packet
///
/// This function is useful to know if there is some data
/// left to be read, without actually reading it.
///
/// \return `true` if all data was read, `false` otherwise
///
/// \see `operator` bool
///
////////////////////////////////////////////////////////////
[[nodiscard]] bool endOfPacket() const;
////////////////////////////////////////////////////////////
/// \brief Test the validity of the packet, for reading
///
/// This operator allows to test the packet as a boolean
/// variable, to check if a reading operation was successful.
///
/// A packet will be in an invalid state if it has no more
/// data to read.
///
/// This behavior is the same as standard C++ streams.
///
/// Usage example:
/// \code
/// float x;
/// packet >> x;
/// if (packet)
/// {
/// // ok, x was extracted successfully
/// }
///
/// // -- or --
///
/// float x;
/// if (packet >> x)
/// {
/// // ok, x was extracted successfully
/// }
/// \endcode
///
/// \return `true` if last data extraction from packet was successful
///
/// \see `endOfPacket`
///
////////////////////////////////////////////////////////////
explicit operator bool() const;
////////////////////////////////////////////////////////////
/// Overload of `operator>>` to read data from the packet
///
////////////////////////////////////////////////////////////
Packet& operator>>(bool& data);
////////////////////////////////////////////////////////////
/// \overload
////////////////////////////////////////////////////////////
Packet& operator>>(std::int8_t& data);
////////////////////////////////////////////////////////////
/// \overload
////////////////////////////////////////////////////////////
Packet& operator>>(std::uint8_t& data);
////////////////////////////////////////////////////////////
/// \overload
////////////////////////////////////////////////////////////
Packet& operator>>(std::int16_t& data);
////////////////////////////////////////////////////////////
/// \overload
////////////////////////////////////////////////////////////
Packet& operator>>(std::uint16_t& data);
////////////////////////////////////////////////////////////
/// \overload
////////////////////////////////////////////////////////////
Packet& operator>>(std::int32_t& data);
////////////////////////////////////////////////////////////
/// \overload
////////////////////////////////////////////////////////////
Packet& operator>>(std::uint32_t& data);
////////////////////////////////////////////////////////////
/// \overload
////////////////////////////////////////////////////////////
Packet& operator>>(std::int64_t& data);
////////////////////////////////////////////////////////////
/// \overload
////////////////////////////////////////////////////////////
Packet& operator>>(std::uint64_t& data);
////////////////////////////////////////////////////////////
/// \overload
////////////////////////////////////////////////////////////
Packet& operator>>(float& data);
////////////////////////////////////////////////////////////
/// \overload
////////////////////////////////////////////////////////////
Packet& operator>>(double& data);
////////////////////////////////////////////////////////////
/// \overload
////////////////////////////////////////////////////////////
Packet& operator>>(char* data);
////////////////////////////////////////////////////////////
/// \overload
////////////////////////////////////////////////////////////
Packet& operator>>(std::string& data);
////////////////////////////////////////////////////////////
/// \overload
////////////////////////////////////////////////////////////
Packet& operator>>(wchar_t* data);
////////////////////////////////////////////////////////////
/// \overload
////////////////////////////////////////////////////////////
Packet& operator>>(std::wstring& data);
////////////////////////////////////////////////////////////
/// \overload
////////////////////////////////////////////////////////////
Packet& operator>>(String& data);
////////////////////////////////////////////////////////////
/// Overload of `operator<<` to write data into the packet
///
////////////////////////////////////////////////////////////
Packet& operator<<(bool data);
////////////////////////////////////////////////////////////
/// \overload
////////////////////////////////////////////////////////////
Packet& operator<<(std::int8_t data);
////////////////////////////////////////////////////////////
/// \overload
////////////////////////////////////////////////////////////
Packet& operator<<(std::uint8_t data);
////////////////////////////////////////////////////////////
/// \overload
////////////////////////////////////////////////////////////
Packet& operator<<(std::int16_t data);
////////////////////////////////////////////////////////////
/// \overload
////////////////////////////////////////////////////////////
Packet& operator<<(std::uint16_t data);
////////////////////////////////////////////////////////////
/// \overload
////////////////////////////////////////////////////////////
Packet& operator<<(std::int32_t data);
////////////////////////////////////////////////////////////
/// \overload
////////////////////////////////////////////////////////////
Packet& operator<<(std::uint32_t data);
////////////////////////////////////////////////////////////
/// \overload
////////////////////////////////////////////////////////////
Packet& operator<<(std::int64_t data);
////////////////////////////////////////////////////////////
/// \overload
////////////////////////////////////////////////////////////
Packet& operator<<(std::uint64_t data);
////////////////////////////////////////////////////////////
/// \overload
////////////////////////////////////////////////////////////
Packet& operator<<(float data);
////////////////////////////////////////////////////////////
/// \overload
////////////////////////////////////////////////////////////
Packet& operator<<(double data);
////////////////////////////////////////////////////////////
/// \overload
////////////////////////////////////////////////////////////
Packet& operator<<(const char* data);
////////////////////////////////////////////////////////////
/// \overload
////////////////////////////////////////////////////////////
Packet& operator<<(const std::string& data);
////////////////////////////////////////////////////////////
/// \overload
////////////////////////////////////////////////////////////
Packet& operator<<(const wchar_t* data);
////////////////////////////////////////////////////////////
/// \overload
////////////////////////////////////////////////////////////
Packet& operator<<(const std::wstring& data);
////////////////////////////////////////////////////////////
/// \overload
////////////////////////////////////////////////////////////
Packet& operator<<(const String& data);
protected:
friend class TcpSocket;
friend class UdpSocket;
////////////////////////////////////////////////////////////
/// \brief Called before the packet is sent over the network
///
/// This function can be defined by derived classes to
/// transform the data before it is sent; this can be
/// used for compression, encryption, etc.
/// The function must return a pointer to the modified data,
/// as well as the number of bytes pointed.
/// The default implementation provides the packet's data
/// without transforming it.
///
/// \param size Variable to fill with the size of data to send
///
/// \return Pointer to the array of bytes to send
///
/// \see `onReceive`
///
////////////////////////////////////////////////////////////
virtual const void* onSend(std::size_t& size);
////////////////////////////////////////////////////////////
/// \brief Called after the packet is received over the network
///
/// This function can be defined by derived classes to
/// transform the data after it is received; this can be
/// used for decompression, decryption, etc.
/// The function receives a pointer to the received data,
/// and must fill the packet with the transformed bytes.
/// The default implementation fills the packet directly
/// without transforming the data.
///
/// \param data Pointer to the received bytes
/// \param size Number of bytes
///
/// \see `onSend`
///
////////////////////////////////////////////////////////////
virtual void onReceive(const void* data, std::size_t size);
private:
////////////////////////////////////////////////////////////
/// \brief Check if the packet can extract a given number of bytes
///
/// This function updates accordingly the state of the packet.
///
/// \param size Size to check
///
/// \return `true` if \a size bytes can be read from the packet
///
////////////////////////////////////////////////////////////
bool checkSize(std::size_t size);
////////////////////////////////////////////////////////////
// Member data
////////////////////////////////////////////////////////////
std::vector<std::byte> m_data; //!< Data stored in the packet
std::size_t m_readPos{}; //!< Current reading position in the packet
std::size_t m_sendPos{}; //!< Current send position in the packet (for handling partial sends)
bool m_isValid{true}; //!< Reading state of the packet
};
} // namespace sf
////////////////////////////////////////////////////////////
/// \class sf::Packet
/// \ingroup network
///
/// Packets provide a safe and easy way to serialize data,
/// in order to send it over the network using sockets
/// (`sf::TcpSocket`, `sf::UdpSocket`).
///
/// Packets solve 2 fundamental problems that arise when
/// transferring data over the network:
/// \li data is interpreted correctly according to the endianness
/// \li the bounds of the packet are preserved (one send == one receive)
///
/// The `sf::Packet` class provides both input and output modes.
/// It is designed to follow the behavior of standard C++ streams,
/// using operators >> and << to extract and insert data.
///
/// It is recommended to use only fixed-size types (like `std::int32_t`, etc.),
/// to avoid possible differences between the sender and the receiver.
/// Indeed, the native C++ types may have different sizes on two platforms
/// and your data may be corrupted if that happens.
///
/// Usage example:
/// \code
/// std::uint32_t x = 24;
/// std::string s = "hello";
/// double d = 5.89;
///
/// // Group the variables to send into a packet
/// sf::Packet packet;
/// packet << x << s << d;
///
/// // Send it over the network (socket is a valid sf::TcpSocket)
/// socket.send(packet);
///
/// -----------------------------------------------------------------
///
/// // Receive the packet at the other end
/// sf::Packet packet;
/// socket.receive(packet);
///
/// // Extract the variables contained in the packet
/// std::uint32_t x;
/// std::string s;
/// double d;
/// if (packet >> x >> s >> d)
/// {
/// // Data extracted successfully...
/// }
/// \endcode
///
/// Packets have built-in `operator>>` and << overloads for
/// standard types:
/// \li `bool`
/// \li fixed-size integer types (`int[8|16|32]_t`, `uint[8|16|32]_t`)
/// \li floating point numbers (`float`, `double`)
/// \li string types (`char*`, `wchar_t*`, `std::string`, `std::wstring`, `sf::String`)
///
/// Like standard streams, it is also possible to define your own
/// overloads of operators >> and << in order to handle your
/// custom types.
///
/// \code
/// struct MyStruct
/// {
/// float number{};
/// std::int8_t integer{};
/// std::string str;
/// };
///
/// sf::Packet& operator <<(sf::Packet& packet, const MyStruct& m)
/// {
/// return packet << m.number << m.integer << m.str;
/// }
///
/// sf::Packet& operator >>(sf::Packet& packet, MyStruct& m)
/// {
/// return packet >> m.number >> m.integer >> m.str;
/// }
/// \endcode
///
/// Packets also provide an extra feature that allows to apply
/// custom transformations to the data before it is sent,
/// and after it is received. This is typically used to
/// handle automatic compression or encryption of the data.
/// This is achieved by inheriting from `sf::Packet`, and overriding
/// the onSend and onReceive functions.
///
/// Here is an example:
/// \code
/// class ZipPacket : public sf::Packet
/// {
/// const void* onSend(std::size_t& size) override
/// {
/// const void* srcData = getData();
/// std::size_t srcSize = getDataSize();
///
/// return MySuperZipFunction(srcData, srcSize, &size);
/// }
///
/// void onReceive(const void* data, std::size_t size) override
/// {
/// std::size_t dstSize;
/// const void* dstData = MySuperUnzipFunction(data, size, &dstSize);
///
/// append(dstData, dstSize);
/// }
/// };
///
/// // Use like regular packets:
/// ZipPacket packet;
/// packet << x << s << d;
/// ...
/// \endcode
///
/// \see `sf::TcpSocket`, `sf::UdpSocket`
///
////////////////////////////////////////////////////////////

View File

@ -1,229 +0,0 @@
////////////////////////////////////////////////////////////
//
// SFML - Simple and Fast Multimedia Library
// Copyright (C) 2007-2025 Laurent Gomila (laurent@sfml-dev.org)
//
// This software is provided 'as-is', without any express or implied warranty.
// In no event will the authors be held liable for any damages arising from the use of this software.
//
// Permission is granted to anyone to use this software for any purpose,
// including commercial applications, and to alter it and redistribute it freely,
// subject to the following restrictions:
//
// 1. The origin of this software must not be misrepresented;
// you must not claim that you wrote the original software.
// If you use this software in a product, an acknowledgment
// in the product documentation would be appreciated but is not required.
//
// 2. Altered source versions must be plainly marked as such,
// and must not be misrepresented as being the original software.
//
// 3. This notice may not be removed or altered from any source distribution.
//
////////////////////////////////////////////////////////////
#pragma once
////////////////////////////////////////////////////////////
// Headers
////////////////////////////////////////////////////////////
#include <SFML/Network/Export.hpp>
#include <SFML/Network/SocketHandle.hpp>
namespace sf
{
////////////////////////////////////////////////////////////
/// \brief Base class for all the socket types
///
////////////////////////////////////////////////////////////
class SFML_NETWORK_API Socket
{
public:
////////////////////////////////////////////////////////////
/// \brief Status codes that may be returned by socket functions
///
////////////////////////////////////////////////////////////
enum class Status
{
Done, //!< The socket has sent / received the data
NotReady, //!< The socket is not ready to send / receive data yet
Partial, //!< The socket sent a part of the data
Disconnected, //!< The TCP socket has been disconnected
Error //!< An unexpected error happened
};
////////////////////////////////////////////////////////////
/// \brief Some special values used by sockets
///
////////////////////////////////////////////////////////////
// NOLINTNEXTLINE(readability-identifier-naming)
static constexpr unsigned short AnyPort{0}; //!< Special value that tells the system to pick any available port
////////////////////////////////////////////////////////////
/// \brief Destructor
///
////////////////////////////////////////////////////////////
virtual ~Socket();
////////////////////////////////////////////////////////////
/// \brief Deleted copy constructor
///
////////////////////////////////////////////////////////////
Socket(const Socket&) = delete;
////////////////////////////////////////////////////////////
/// \brief Deleted copy assignment
///
////////////////////////////////////////////////////////////
Socket& operator=(const Socket&) = delete;
////////////////////////////////////////////////////////////
/// \brief Move constructor
///
////////////////////////////////////////////////////////////
Socket(Socket&& socket) noexcept;
////////////////////////////////////////////////////////////
/// \brief Move assignment
///
////////////////////////////////////////////////////////////
Socket& operator=(Socket&& socket) noexcept;
////////////////////////////////////////////////////////////
/// \brief Set the blocking state of the socket
///
/// In blocking mode, calls will not return until they have
/// completed their task. For example, a call to Receive in
/// blocking mode won't return until some data was actually
/// received.
/// In non-blocking mode, calls will always return immediately,
/// using the return code to signal whether there was data
/// available or not.
/// By default, all sockets are blocking.
///
/// \param blocking `true` to set the socket as blocking, `false` for non-blocking
///
/// \see `isBlocking`
///
////////////////////////////////////////////////////////////
void setBlocking(bool blocking);
////////////////////////////////////////////////////////////
/// \brief Tell whether the socket is in blocking or non-blocking mode
///
/// \return `true` if the socket is blocking, `false` otherwise
///
/// \see `setBlocking`
///
////////////////////////////////////////////////////////////
[[nodiscard]] bool isBlocking() const;
protected:
////////////////////////////////////////////////////////////
/// \brief Types of protocols that the socket can use
///
////////////////////////////////////////////////////////////
enum class Type
{
Tcp, //!< TCP protocol
Udp //!< UDP protocol
};
////////////////////////////////////////////////////////////
/// \brief Default constructor
///
/// This constructor can only be accessed by derived classes.
///
/// \param type Type of the socket (TCP or UDP)
///
////////////////////////////////////////////////////////////
explicit Socket(Type type);
////////////////////////////////////////////////////////////
/// \brief Return the internal handle of the socket
///
/// The returned handle may be invalid if the socket
/// was not created yet (or already destroyed).
/// This function can only be accessed by derived classes.
///
/// \return The internal (OS-specific) handle of the socket
///
////////////////////////////////////////////////////////////
[[nodiscard]] SocketHandle getNativeHandle() const;
////////////////////////////////////////////////////////////
/// \brief Create the internal representation of the socket
///
/// This function can only be accessed by derived classes.
///
////////////////////////////////////////////////////////////
void create();
////////////////////////////////////////////////////////////
/// \brief Create the internal representation of the socket
/// from a socket handle
///
/// This function can only be accessed by derived classes.
///
/// \param handle OS-specific handle of the socket to wrap
///
////////////////////////////////////////////////////////////
void create(SocketHandle handle);
////////////////////////////////////////////////////////////
/// \brief Close the socket gracefully
///
/// This function can only be accessed by derived classes.
///
////////////////////////////////////////////////////////////
void close();
private:
friend class SocketSelector;
////////////////////////////////////////////////////////////
// Member data
////////////////////////////////////////////////////////////
Type m_type; //!< Type of the socket (TCP or UDP)
SocketHandle m_socket; //!< Socket descriptor
bool m_isBlocking{true}; //!< Current blocking mode of the socket
};
} // namespace sf
////////////////////////////////////////////////////////////
/// \class sf::Socket
/// \ingroup network
///
/// This class mainly defines internal stuff to be used by
/// derived classes.
///
/// The only public features that it defines, and which
/// is therefore common to all the socket classes, is the
/// blocking state. All sockets can be set as blocking or
/// non-blocking.
///
/// In blocking mode, socket functions will hang until
/// the operation completes, which means that the entire
/// program (well, in fact the current thread if you use
/// multiple ones) will be stuck waiting for your socket
/// operation to complete.
///
/// In non-blocking mode, all the socket functions will
/// return immediately. If the socket is not ready to complete
/// the requested operation, the function simply returns
/// the proper status code (`Socket::Status::NotReady`).
///
/// The default mode, which is blocking, is the one that is
/// generally used, in combination with threads or selectors.
/// The non-blocking mode is rather used in real-time
/// applications that run an endless loop that can poll
/// the socket often enough, and cannot afford blocking
/// this loop.
///
/// \see `sf::TcpListener`, `sf::TcpSocket`, `sf::UdpSocket`
///
////////////////////////////////////////////////////////////

View File

@ -1,52 +0,0 @@
////////////////////////////////////////////////////////////
//
// SFML - Simple and Fast Multimedia Library
// Copyright (C) 2007-2025 Laurent Gomila (laurent@sfml-dev.org)
//
// This software is provided 'as-is', without any express or implied warranty.
// In no event will the authors be held liable for any damages arising from the use of this software.
//
// Permission is granted to anyone to use this software for any purpose,
// including commercial applications, and to alter it and redistribute it freely,
// subject to the following restrictions:
//
// 1. The origin of this software must not be misrepresented;
// you must not claim that you wrote the original software.
// If you use this software in a product, an acknowledgment
// in the product documentation would be appreciated but is not required.
//
// 2. Altered source versions must be plainly marked as such,
// and must not be misrepresented as being the original software.
//
// 3. This notice may not be removed or altered from any source distribution.
//
////////////////////////////////////////////////////////////
#pragma once
////////////////////////////////////////////////////////////
// Headers
////////////////////////////////////////////////////////////
#include <SFML/Config.hpp>
#if defined(SFML_SYSTEM_WINDOWS)
#include <basetsd.h>
#endif
namespace sf
{
////////////////////////////////////////////////////////////
// Low-level socket handle type, specific to each platform
////////////////////////////////////////////////////////////
#if defined(SFML_SYSTEM_WINDOWS)
using SocketHandle = UINT_PTR;
#else
using SocketHandle = int;
#endif
} // namespace sf

View File

@ -1,273 +0,0 @@
////////////////////////////////////////////////////////////
//
// SFML - Simple and Fast Multimedia Library
// Copyright (C) 2007-2025 Laurent Gomila (laurent@sfml-dev.org)
//
// This software is provided 'as-is', without any express or implied warranty.
// In no event will the authors be held liable for any damages arising from the use of this software.
//
// Permission is granted to anyone to use this software for any purpose,
// including commercial applications, and to alter it and redistribute it freely,
// subject to the following restrictions:
//
// 1. The origin of this software must not be misrepresented;
// you must not claim that you wrote the original software.
// If you use this software in a product, an acknowledgment
// in the product documentation would be appreciated but is not required.
//
// 2. Altered source versions must be plainly marked as such,
// and must not be misrepresented as being the original software.
//
// 3. This notice may not be removed or altered from any source distribution.
//
////////////////////////////////////////////////////////////
#pragma once
////////////////////////////////////////////////////////////
// Headers
////////////////////////////////////////////////////////////
#include <SFML/Network/Export.hpp>
#include <SFML/System/Time.hpp>
#include <memory>
namespace sf
{
class Socket;
////////////////////////////////////////////////////////////
/// \brief Multiplexer that allows to read from multiple sockets
///
////////////////////////////////////////////////////////////
class SFML_NETWORK_API SocketSelector
{
public:
////////////////////////////////////////////////////////////
/// \brief Default constructor
///
////////////////////////////////////////////////////////////
SocketSelector();
////////////////////////////////////////////////////////////
/// \brief Destructor
///
////////////////////////////////////////////////////////////
~SocketSelector();
////////////////////////////////////////////////////////////
/// \brief Copy constructor
///
/// \param copy Instance to copy
///
////////////////////////////////////////////////////////////
SocketSelector(const SocketSelector& copy);
////////////////////////////////////////////////////////////
/// \brief Overload of assignment operator
///
/// \param right Instance to assign
///
/// \return Reference to self
///
////////////////////////////////////////////////////////////
SocketSelector& operator=(const SocketSelector& right);
////////////////////////////////////////////////////////////
/// \brief Move constructor
///
////////////////////////////////////////////////////////////
SocketSelector(SocketSelector&&) noexcept;
////////////////////////////////////////////////////////////
/// \brief Move assignment
///
////////////////////////////////////////////////////////////
SocketSelector& operator=(SocketSelector&&) noexcept;
////////////////////////////////////////////////////////////
/// \brief Add a new socket to the selector
///
/// This function keeps a weak reference to the socket,
/// so you have to make sure that the socket is not destroyed
/// while it is stored in the selector.
/// This function does nothing if the socket is not valid.
///
/// \param socket Reference to the socket to add
///
/// \see `remove`, `clear`
///
////////////////////////////////////////////////////////////
void add(Socket& socket);
////////////////////////////////////////////////////////////
/// \brief Remove a socket from the selector
///
/// This function doesn't destroy the socket, it simply
/// removes the reference that the selector has to it.
///
/// \param socket Reference to the socket to remove
///
/// \see `add`, `clear`
///
////////////////////////////////////////////////////////////
void remove(Socket& socket);
////////////////////////////////////////////////////////////
/// \brief Remove all the sockets stored in the selector
///
/// This function doesn't destroy any instance, it simply
/// removes all the references that the selector has to
/// external sockets.
///
/// \see `add`, `remove`
///
////////////////////////////////////////////////////////////
void clear();
////////////////////////////////////////////////////////////
/// \brief Wait until one or more sockets are ready to receive
///
/// This function returns as soon as at least one socket has
/// some data available to be received. To know which sockets are
/// ready, use the `isReady` function.
/// If you use a timeout and no socket is ready before the timeout
/// is over, the function returns `false`.
///
/// \param timeout Maximum time to wait, (use Time::Zero for infinity)
///
/// \return `true` if there are sockets ready, `false` otherwise
///
/// \see `isReady`
///
////////////////////////////////////////////////////////////
[[nodiscard]] bool wait(Time timeout = Time::Zero);
////////////////////////////////////////////////////////////
/// \brief Test a socket to know if it is ready to receive data
///
/// This function must be used after a call to Wait, to know
/// which sockets are ready to receive data. If a socket is
/// ready, a call to receive will never block because we know
/// that there is data available to read.
/// Note that if this function returns `true` for a TcpListener,
/// this means that it is ready to accept a new connection.
///
/// \param socket Socket to test
///
/// \return `true` if the socket is ready to read, `false` otherwise
///
/// \see `isReady`
///
////////////////////////////////////////////////////////////
[[nodiscard]] bool isReady(Socket& socket) const;
private:
struct SocketSelectorImpl;
////////////////////////////////////////////////////////////
// Member data
////////////////////////////////////////////////////////////
std::unique_ptr<SocketSelectorImpl> m_impl; //!< Opaque pointer to the implementation (which requires OS-specific types)
};
} // namespace sf
////////////////////////////////////////////////////////////
/// \class sf::SocketSelector
/// \ingroup network
///
/// Socket selectors provide a way to wait until some data is
/// available on a set of sockets, instead of just one. This
/// is convenient when you have multiple sockets that may
/// possibly receive data, but you don't know which one will
/// be ready first. In particular, it avoids to use a thread
/// for each socket; with selectors, a single thread can handle
/// all the sockets.
///
/// All types of sockets can be used in a selector:
/// \li `sf::TcpListener`
/// \li `sf::TcpSocket`
/// \li `sf::UdpSocket`
///
/// A selector doesn't store its own copies of the sockets
/// (socket classes are not copyable anyway), it simply keeps
/// a reference to the original sockets that you pass to the
/// "add" function. Therefore, you can't use the selector as a
/// socket container, you must store them outside and make sure
/// that they are alive as long as they are used in the selector.
///
/// Using a selector is simple:
/// \li populate the selector with all the sockets that you want to observe
/// \li make it wait until there is data available on any of the sockets
/// \li test each socket to find out which ones are ready
///
/// Usage example:
/// \code
/// // Create a socket to listen to new connections
/// sf::TcpListener listener;
/// if (listener.listen(55001) != sf::Socket::Status::Done)
/// {
/// // Handle error...
/// }
///
/// // Create a list to store the future clients
/// std::vector<sf::TcpSocket> clients;
///
/// // Create a selector
/// sf::SocketSelector selector;
///
/// // Add the listener to the selector
/// selector.add(listener);
///
/// // Endless loop that waits for new connections
/// while (running)
/// {
/// // Make the selector wait for data on any socket
/// if (selector.wait())
/// {
/// // Test the listener
/// if (selector.isReady(listener))
/// {
/// // The listener is ready: there is a pending connection
/// sf::TcpSocket client;
/// if (listener.accept(client) == sf::Socket::Status::Done)
/// {
/// // Add the new client to the selector so that we will
/// // be notified when they send something
/// selector.add(client);
///
/// // Add the new client to the clients list
/// clients.push_back(std::move(client));
/// }
/// else
/// {
/// // Handle error...
/// }
/// }
/// else
/// {
/// // The listener socket is not ready, test all other sockets (the clients)
/// for (sf::TcpSocket& client : clients)
/// {
/// if (selector.isReady(client))
/// {
/// // The client has sent some data, we can receive it
/// sf::Packet packet;
/// if (client.receive(packet) == sf::Socket::Status::Done)
/// {
/// ...
/// }
/// }
/// }
/// }
/// }
/// }
/// \endcode
///
/// \see `sf::Socket`
///
////////////////////////////////////////////////////////////

View File

@ -1,166 +0,0 @@
////////////////////////////////////////////////////////////
//
// SFML - Simple and Fast Multimedia Library
// Copyright (C) 2007-2025 Laurent Gomila (laurent@sfml-dev.org)
//
// This software is provided 'as-is', without any express or implied warranty.
// In no event will the authors be held liable for any damages arising from the use of this software.
//
// Permission is granted to anyone to use this software for any purpose,
// including commercial applications, and to alter it and redistribute it freely,
// subject to the following restrictions:
//
// 1. The origin of this software must not be misrepresented;
// you must not claim that you wrote the original software.
// If you use this software in a product, an acknowledgment
// in the product documentation would be appreciated but is not required.
//
// 2. Altered source versions must be plainly marked as such,
// and must not be misrepresented as being the original software.
//
// 3. This notice may not be removed or altered from any source distribution.
//
////////////////////////////////////////////////////////////
#pragma once
////////////////////////////////////////////////////////////
// Headers
////////////////////////////////////////////////////////////
#include <SFML/Network/Export.hpp>
#include <SFML/Network/IpAddress.hpp>
#include <SFML/Network/Socket.hpp>
namespace sf
{
class TcpSocket;
////////////////////////////////////////////////////////////
/// \brief Socket that listens to new TCP connections
///
////////////////////////////////////////////////////////////
class SFML_NETWORK_API TcpListener : public Socket
{
public:
////////////////////////////////////////////////////////////
/// \brief Default constructor
///
////////////////////////////////////////////////////////////
TcpListener();
////////////////////////////////////////////////////////////
/// \brief Get the port to which the socket is bound locally
///
/// If the socket is not listening to a port, this function
/// returns 0.
///
/// \return Port to which the socket is bound
///
/// \see `listen`
///
////////////////////////////////////////////////////////////
[[nodiscard]] unsigned short getLocalPort() const;
////////////////////////////////////////////////////////////
/// \brief Start listening for incoming connection attempts
///
/// This function makes the socket start listening on the
/// specified port, waiting for incoming connection attempts.
///
/// If the socket is already listening on a port when this
/// function is called, it will stop listening on the old
/// port before starting to listen on the new port.
///
/// When providing `sf::Socket::AnyPort` as port, the listener
/// will request an available port from the system.
/// The chosen port can be retrieved by calling `getLocalPort()`.
///
/// \param port Port to listen on for incoming connection attempts
/// \param address Address of the interface to listen on
///
/// \return Status code
///
/// \see `accept`, `close`
///
////////////////////////////////////////////////////////////
[[nodiscard]] Status listen(unsigned short port, IpAddress address = IpAddress::Any);
////////////////////////////////////////////////////////////
/// \brief Stop listening and close the socket
///
/// This function gracefully stops the listener. If the
/// socket is not listening, this function has no effect.
///
/// \see `listen`
///
////////////////////////////////////////////////////////////
void close();
////////////////////////////////////////////////////////////
/// \brief Accept a new connection
///
/// If the socket is in blocking mode, this function will
/// not return until a connection is actually received.
///
/// \param socket Socket that will hold the new connection
///
/// \return Status code
///
/// \see `listen`
///
////////////////////////////////////////////////////////////
[[nodiscard]] Status accept(TcpSocket& socket);
};
} // namespace sf
////////////////////////////////////////////////////////////
/// \class sf::TcpListener
/// \ingroup network
///
/// A listener socket is a special type of socket that listens to
/// a given port and waits for connections on that port.
/// This is all it can do.
///
/// When a new connection is received, you must call accept and
/// the listener returns a new instance of `sf::TcpSocket` that
/// is properly initialized and can be used to communicate with
/// the new client.
///
/// Listener sockets are specific to the TCP protocol,
/// UDP sockets are connectionless and can therefore communicate
/// directly. As a consequence, a listener socket will always
/// return the new connections as `sf::TcpSocket` instances.
///
/// A listener is automatically closed on destruction, like all
/// other types of socket. However if you want to stop listening
/// before the socket is destroyed, you can call its `close()`
/// function.
///
/// Usage example:
/// \code
/// // Create a listener socket and make it wait for new
/// // connections on port 55001
/// sf::TcpListener listener;
/// listener.listen(55001);
///
/// // Endless loop that waits for new connections
/// while (running)
/// {
/// sf::TcpSocket client;
/// if (listener.accept(client) == sf::Socket::Done)
/// {
/// // A new client just connected!
/// std::cout << "New connection received from " << client.getRemoteAddress().value() << std::endl;
/// doSomethingWith(client);
/// }
/// }
/// \endcode
///
/// \see `sf::TcpSocket`, `sf::Socket`
///
////////////////////////////////////////////////////////////

View File

@ -1,317 +0,0 @@
////////////////////////////////////////////////////////////
//
// SFML - Simple and Fast Multimedia Library
// Copyright (C) 2007-2025 Laurent Gomila (laurent@sfml-dev.org)
//
// This software is provided 'as-is', without any express or implied warranty.
// In no event will the authors be held liable for any damages arising from the use of this software.
//
// Permission is granted to anyone to use this software for any purpose,
// including commercial applications, and to alter it and redistribute it freely,
// subject to the following restrictions:
//
// 1. The origin of this software must not be misrepresented;
// you must not claim that you wrote the original software.
// If you use this software in a product, an acknowledgment
// in the product documentation would be appreciated but is not required.
//
// 2. Altered source versions must be plainly marked as such,
// and must not be misrepresented as being the original software.
//
// 3. This notice may not be removed or altered from any source distribution.
//
////////////////////////////////////////////////////////////
#pragma once
////////////////////////////////////////////////////////////
// Headers
////////////////////////////////////////////////////////////
#include <SFML/Network/Export.hpp>
#include <SFML/Network/Socket.hpp>
#include <SFML/System/Time.hpp>
#include <optional>
#include <vector>
#include <cstddef>
#include <cstdint>
namespace sf
{
class TcpListener;
class IpAddress;
class Packet;
////////////////////////////////////////////////////////////
/// \brief Specialized socket using the TCP protocol
///
////////////////////////////////////////////////////////////
class SFML_NETWORK_API TcpSocket : public Socket
{
public:
////////////////////////////////////////////////////////////
/// \brief Default constructor
///
////////////////////////////////////////////////////////////
TcpSocket();
////////////////////////////////////////////////////////////
/// \brief Get the port to which the socket is bound locally
///
/// If the socket is not connected, this function returns 0.
///
/// \return Port to which the socket is bound
///
/// \see `connect`, `getRemotePort`
///
////////////////////////////////////////////////////////////
[[nodiscard]] unsigned short getLocalPort() const;
////////////////////////////////////////////////////////////
/// \brief Get the address of the connected peer
///
/// If the socket is not connected, this function returns
/// an unset optional.
///
/// \return Address of the remote peer
///
/// \see `getRemotePort`
///
////////////////////////////////////////////////////////////
[[nodiscard]] std::optional<IpAddress> getRemoteAddress() const;
////////////////////////////////////////////////////////////
/// \brief Get the port of the connected peer to which
/// the socket is connected
///
/// If the socket is not connected, this function returns 0.
///
/// \return Remote port to which the socket is connected
///
/// \see `getRemoteAddress`
///
////////////////////////////////////////////////////////////
[[nodiscard]] unsigned short getRemotePort() const;
////////////////////////////////////////////////////////////
/// \brief Connect the socket to a remote peer
///
/// In blocking mode, this function may take a while, especially
/// if the remote peer is not reachable. The last parameter allows
/// you to stop trying to connect after a given timeout.
/// If the socket is already connected, the connection is
/// forcibly disconnected before attempting to connect again.
///
/// \param remoteAddress Address of the remote peer
/// \param remotePort Port of the remote peer
/// \param timeout Optional maximum time to wait
///
/// \return Status code
///
/// \see `disconnect`
///
////////////////////////////////////////////////////////////
[[nodiscard]] Status connect(IpAddress remoteAddress, unsigned short remotePort, Time timeout = Time::Zero);
////////////////////////////////////////////////////////////
/// \brief Disconnect the socket from its remote peer
///
/// This function gracefully closes the connection. If the
/// socket is not connected, this function has no effect.
///
/// \see `connect`
///
////////////////////////////////////////////////////////////
void disconnect();
////////////////////////////////////////////////////////////
/// \brief Send raw data to the remote peer
///
/// To be able to handle partial sends over non-blocking
/// sockets, use the `send(const void*, std::size_t, std::size_t&)`
/// overload instead.
/// This function will fail if the socket is not connected.
///
/// \param data Pointer to the sequence of bytes to send
/// \param size Number of bytes to send
///
/// \return Status code
///
/// \see `receive`
///
////////////////////////////////////////////////////////////
[[nodiscard]] Status send(const void* data, std::size_t size);
////////////////////////////////////////////////////////////
/// \brief Send raw data to the remote peer
///
/// This function will fail if the socket is not connected.
///
/// \param data Pointer to the sequence of bytes to send
/// \param size Number of bytes to send
/// \param sent The number of bytes sent will be written here
///
/// \return Status code
///
/// \see `receive`
///
////////////////////////////////////////////////////////////
[[nodiscard]] Status send(const void* data, std::size_t size, std::size_t& sent);
////////////////////////////////////////////////////////////
/// \brief Receive raw data from the remote peer
///
/// In blocking mode, this function will wait until some
/// bytes are actually received.
/// This function will fail if the socket is not connected.
///
/// \param data Pointer to the array to fill with the received bytes
/// \param size Maximum number of bytes that can be received
/// \param received This variable is filled with the actual number of bytes received
///
/// \return Status code
///
/// \see `send`
///
////////////////////////////////////////////////////////////
[[nodiscard]] Status receive(void* data, std::size_t size, std::size_t& received);
////////////////////////////////////////////////////////////
/// \brief Send a formatted packet of data to the remote peer
///
/// In non-blocking mode, if this function returns `sf::Socket::Status::Partial`,
/// you \em must retry sending the same unmodified packet before sending
/// anything else in order to guarantee the packet arrives at the remote
/// peer uncorrupted.
/// This function will fail if the socket is not connected.
///
/// \param packet Packet to send
///
/// \return Status code
///
/// \see `receive`
///
////////////////////////////////////////////////////////////
[[nodiscard]] Status send(Packet& packet);
////////////////////////////////////////////////////////////
/// \brief Receive a formatted packet of data from the remote peer
///
/// In blocking mode, this function will wait until the whole packet
/// has been received.
/// This function will fail if the socket is not connected.
///
/// \param packet Packet to fill with the received data
///
/// \return Status code
///
/// \see `send`
///
////////////////////////////////////////////////////////////
[[nodiscard]] Status receive(Packet& packet);
private:
friend class TcpListener;
////////////////////////////////////////////////////////////
/// \brief Structure holding the data of a pending packet
///
////////////////////////////////////////////////////////////
struct PendingPacket
{
std::uint32_t size{}; //!< Data of packet size
std::size_t sizeReceived{}; //!< Number of size bytes received so far
std::vector<std::byte> data; //!< Data of the packet
};
////////////////////////////////////////////////////////////
// Member data
////////////////////////////////////////////////////////////
PendingPacket m_pendingPacket; //!< Temporary data of the packet currently being received
std::vector<std::byte> m_blockToSendBuffer; //!< Buffer used to prepare data being sent from the socket
};
} // namespace sf
////////////////////////////////////////////////////////////
/// \class sf::TcpSocket
/// \ingroup network
///
/// TCP is a connected protocol, which means that a TCP
/// socket can only communicate with the host it is connected
/// to. It can't send or receive anything if it is not connected.
///
/// The TCP protocol is reliable but adds a slight overhead.
/// It ensures that your data will always be received in order
/// and without errors (no data corrupted, lost or duplicated).
///
/// When a socket is connected to a remote host, you can
/// retrieve information about this host with the
/// `getRemoteAddress` and `getRemotePort` functions. You can
/// also get the local port to which the socket is bound
/// (which is automatically chosen when the socket is connected),
/// with the getLocalPort function.
///
/// Sending and receiving data can use either the low-level
/// or the high-level functions. The low-level functions
/// process a raw sequence of bytes, and cannot ensure that
/// one call to Send will exactly match one call to Receive
/// at the other end of the socket.
///
/// The high-level interface uses packets (see `sf::Packet`),
/// which are easier to use and provide more safety regarding
/// the data that is exchanged. You can look at the `sf::Packet`
/// class to get more details about how they work.
///
/// The socket is automatically disconnected when it is destroyed,
/// but if you want to explicitly close the connection while
/// the socket instance is still alive, you can call disconnect.
///
/// Usage example:
/// \code
/// // ----- The client -----
///
/// // Create a socket and connect it to 192.168.1.50 on port 55001
/// sf::TcpSocket socket;
/// socket.connect("192.168.1.50", 55001);
///
/// // Send a message to the connected host
/// std::string message = "Hi, I am a client";
/// socket.send(message.c_str(), message.size() + 1);
///
/// // Receive an answer from the server
/// std::array<char, 1024> buffer;
/// std::size_t received = 0;
/// socket.receive(buffer.data(), buffer.size(), received);
/// std::cout << "The server said: " << buffer.data() << std::endl;
///
/// // ----- The server -----
///
/// // Create a listener to wait for incoming connections on port 55001
/// sf::TcpListener listener;
/// listener.listen(55001);
///
/// // Wait for a connection
/// sf::TcpSocket socket;
/// listener.accept(socket);
/// std::cout << "New client connected: " << socket.getRemoteAddress().value() << std::endl;
///
/// // Receive a message from the client
/// std::array<char, 1024> buffer;
/// std::size_t received = 0;
/// socket.receive(buffer.data(), buffer.size(), received);
/// std::cout << "The client said: " << buffer.data() << std::endl;
///
/// // Send an answer
/// std::string message = "Welcome, client";
/// socket.send(message.c_str(), message.size() + 1);
/// \endcode
///
/// \see `sf::Socket`, `sf::UdpSocket`, `sf::Packet`
///
////////////////////////////////////////////////////////////

View File

@ -1,293 +0,0 @@
////////////////////////////////////////////////////////////
//
// SFML - Simple and Fast Multimedia Library
// Copyright (C) 2007-2025 Laurent Gomila (laurent@sfml-dev.org)
//
// This software is provided 'as-is', without any express or implied warranty.
// In no event will the authors be held liable for any damages arising from the use of this software.
//
// Permission is granted to anyone to use this software for any purpose,
// including commercial applications, and to alter it and redistribute it freely,
// subject to the following restrictions:
//
// 1. The origin of this software must not be misrepresented;
// you must not claim that you wrote the original software.
// If you use this software in a product, an acknowledgment
// in the product documentation would be appreciated but is not required.
//
// 2. Altered source versions must be plainly marked as such,
// and must not be misrepresented as being the original software.
//
// 3. This notice may not be removed or altered from any source distribution.
//
////////////////////////////////////////////////////////////
#pragma once
////////////////////////////////////////////////////////////
// Headers
////////////////////////////////////////////////////////////
#include <SFML/Network/Export.hpp>
#include <SFML/Network/IpAddress.hpp>
#include <SFML/Network/Socket.hpp>
#include <optional>
#include <vector>
#include <cstddef>
namespace sf
{
class Packet;
////////////////////////////////////////////////////////////
/// \brief Specialized socket using the UDP protocol
///
////////////////////////////////////////////////////////////
class SFML_NETWORK_API UdpSocket : public Socket
{
public:
////////////////////////////////////////////////////////////
// Constants
////////////////////////////////////////////////////////////
// NOLINTNEXTLINE(readability-identifier-naming)
static constexpr std::size_t MaxDatagramSize{65507}; //!< The maximum number of bytes that can be sent in a single UDP datagram
////////////////////////////////////////////////////////////
/// \brief Default constructor
///
////////////////////////////////////////////////////////////
UdpSocket();
////////////////////////////////////////////////////////////
/// \brief Get the port to which the socket is bound locally
///
/// If the socket is not bound to a port, this function
/// returns 0.
///
/// \return Port to which the socket is bound
///
/// \see `bind`
///
////////////////////////////////////////////////////////////
[[nodiscard]] unsigned short getLocalPort() const;
////////////////////////////////////////////////////////////
/// \brief Bind the socket to a specific port
///
/// Binding the socket to a port is necessary for being
/// able to receive data on that port.
///
/// When providing `sf::Socket::AnyPort` as port, the listener
/// will request an available port from the system.
/// The chosen port can be retrieved by calling `getLocalPort()`.
///
/// Since the socket can only be bound to a single port at
/// any given moment, if it is already bound when this
/// function is called, it will be unbound from the previous
/// port before being bound to the new one.
///
/// \param port Port to bind the socket to
/// \param address Address of the interface to bind to
///
/// \return Status code
///
/// \see `unbind`, `getLocalPort`
///
////////////////////////////////////////////////////////////
[[nodiscard]] Status bind(unsigned short port, IpAddress address = IpAddress::Any);
////////////////////////////////////////////////////////////
/// \brief Unbind the socket from the local port to which it is bound
///
/// The port that the socket was previously bound to is immediately
/// made available to the operating system after this function is called.
/// This means that a subsequent call to `bind()` will be able to re-bind
/// the port if no other process has done so in the mean time.
/// If the socket is not bound to a port, this function has no effect.
///
/// \see `bind`
///
////////////////////////////////////////////////////////////
void unbind();
////////////////////////////////////////////////////////////
/// \brief Send raw data to a remote peer
///
/// Make sure that `size` is not greater than
/// `UdpSocket::MaxDatagramSize`, otherwise this function will
/// fail and no data will be sent.
///
/// \param data Pointer to the sequence of bytes to send
/// \param size Number of bytes to send
/// \param remoteAddress Address of the receiver
/// \param remotePort Port of the receiver to send the data to
///
/// \return Status code
///
/// \see `receive`
///
////////////////////////////////////////////////////////////
[[nodiscard]] Status send(const void* data, std::size_t size, IpAddress remoteAddress, unsigned short remotePort);
////////////////////////////////////////////////////////////
/// \brief Receive raw data from a remote peer
///
/// In blocking mode, this function will wait until some
/// bytes are actually received.
/// Be careful to use a buffer which is large enough for
/// the data that you intend to receive, if it is too small
/// then an error will be returned and *all* the data will
/// be lost.
///
/// \param data Pointer to the array to fill with the received bytes
/// \param size Maximum number of bytes that can be received
/// \param received This variable is filled with the actual number of bytes received
/// \param remoteAddress Address of the peer that sent the data
/// \param remotePort Port of the peer that sent the data
///
/// \return Status code
///
/// \see `send`
///
////////////////////////////////////////////////////////////
[[nodiscard]] Status receive(void* data,
std::size_t size,
std::size_t& received,
std::optional<IpAddress>& remoteAddress,
unsigned short& remotePort);
////////////////////////////////////////////////////////////
/// \brief Send a formatted packet of data to a remote peer
///
/// Make sure that the packet size is not greater than
/// `UdpSocket::MaxDatagramSize`, otherwise this function will
/// fail and no data will be sent.
///
/// \param packet Packet to send
/// \param remoteAddress Address of the receiver
/// \param remotePort Port of the receiver to send the data to
///
/// \return Status code
///
/// \see `receive`
///
////////////////////////////////////////////////////////////
[[nodiscard]] Status send(Packet& packet, IpAddress remoteAddress, unsigned short remotePort);
////////////////////////////////////////////////////////////
/// \brief Receive a formatted packet of data from a remote peer
///
/// In blocking mode, this function will wait until the whole packet
/// has been received.
///
/// \param packet Packet to fill with the received data
/// \param remoteAddress Address of the peer that sent the data
/// \param remotePort Port of the peer that sent the data
///
/// \return Status code
///
/// \see `send`
///
////////////////////////////////////////////////////////////
[[nodiscard]] Status receive(Packet& packet, std::optional<IpAddress>& remoteAddress, unsigned short& remotePort);
private:
////////////////////////////////////////////////////////////
// Member data
////////////////////////////////////////////////////////////
std::vector<std::byte> m_buffer{MaxDatagramSize}; //!< Temporary buffer holding the received data in Receive(Packet)
};
} // namespace sf
////////////////////////////////////////////////////////////
/// \class sf::UdpSocket
/// \ingroup network
///
/// A UDP socket is a connectionless socket. Instead of
/// connecting once to a remote host, like TCP sockets,
/// it can send to and receive from any host at any time.
///
/// It is a datagram protocol: bounded blocks of data (datagrams)
/// are transferred over the network rather than a continuous
/// stream of data (TCP). Therefore, one call to send will always
/// match one call to receive (if the datagram is not lost),
/// with the same data that was sent.
///
/// The UDP protocol is lightweight but unreliable. Unreliable
/// means that datagrams may be duplicated, be lost or
/// arrive reordered. However, if a datagram arrives, its
/// data is guaranteed to be valid.
///
/// UDP is generally used for real-time communication
/// (audio or video streaming, real-time games, etc.) where
/// speed is crucial and lost data doesn't matter much.
///
/// Sending and receiving data can use either the low-level
/// or the high-level functions. The low-level functions
/// process a raw sequence of bytes, whereas the high-level
/// interface uses packets (see `sf::Packet`), which are easier
/// to use and provide more safety regarding the data that is
/// exchanged. You can look at the `sf::Packet` class to get
/// more details about how they work.
///
/// It is important to note that `UdpSocket` is unable to send
/// datagrams bigger than `MaxDatagramSize`. In this case, it
/// returns an error and doesn't send anything. This applies
/// to both raw data and packets. Indeed, even packets are
/// unable to split and recompose data, due to the unreliability
/// of the protocol (dropped, mixed or duplicated datagrams may
/// lead to a big mess when trying to recompose a packet).
///
/// If the socket is bound to a port, it is automatically
/// unbound from it when the socket is destroyed. However,
/// you can unbind the socket explicitly with the Unbind
/// function if necessary, to stop receiving messages or
/// make the port available for other sockets.
///
/// Usage example:
/// \code
/// // ----- The client -----
///
/// // Create a socket and bind it to the port 55001
/// sf::UdpSocket socket;
/// socket.bind(55001);
///
/// // Send a message to 192.168.1.50 on port 55002
/// std::string message = "Hi, I am " + sf::IpAddress::getLocalAddress().toString();
/// socket.send(message.c_str(), message.size() + 1, "192.168.1.50", 55002);
///
/// // Receive an answer (most likely from 192.168.1.50, but could be anyone else)
/// std::array<char, 1024> buffer;
/// std::size_t received = 0;
/// std::optional<sf::IpAddress> sender;
/// unsigned short port;
/// if (socket.receive(buffer.data(), buffer.size(), received, sender, port) == sf::Socket::Status::Done)
/// std::cout << sender->toString() << " said: " << buffer.data() << std::endl;
///
/// // ----- The server -----
///
/// // Create a socket and bind it to the port 55002
/// sf::UdpSocket socket;
/// socket.bind(55002);
///
/// // Receive a message from anyone
/// std::array<char, 1024> buffer;
/// std::size_t received = 0;
/// std::optional<sf::IpAddress> sender;
/// unsigned short port;
/// if (socket.receive(buffer.data(), buffer.size(), received, sender, port) == sf::Socket::Status::Done)
/// std::cout << sender->toString() << " said: " << buffer.data() << std::endl;
///
/// // Send an answer
/// std::string message = "Welcome " + sender.toString();
/// socket.send(message.c_str(), message.size() + 1, sender, port);
/// \endcode
///
/// \see `sf::Socket`, `sf::TcpSocket`, `sf::Packet`
///
////////////////////////////////////////////////////////////

View File

@ -1,78 +0,0 @@
////////////////////////////////////////////////////////////
//
// SFML - Simple and Fast Multimedia Library
// Copyright (C) 2007-2025 Laurent Gomila (laurent@sfml-dev.org)
//
// This software is provided 'as-is', without any express or implied warranty.
// In no event will the authors be held liable for any damages arising from the use of this software.
//
// Permission is granted to anyone to use this software for any purpose,
// including commercial applications, and to alter it and redistribute it freely,
// subject to the following restrictions:
//
// 1. The origin of this software must not be misrepresented;
// you must not claim that you wrote the original software.
// If you use this software in a product, an acknowledgment
// in the product documentation would be appreciated but is not required.
//
// 2. Altered source versions must be plainly marked as such,
// and must not be misrepresented as being the original software.
//
// 3. This notice may not be removed or altered from any source distribution.
//
////////////////////////////////////////////////////////////
#pragma once
////////////////////////////////////////////////////////////
/// Headers
////////////////////////////////////////////////////////////
#include <SFML/Config.hpp>
////////////////////////////////////////////////////////////
/// This file just includes the OpenGL headers,
/// which have actually different paths on each system
////////////////////////////////////////////////////////////
#if defined(SFML_SYSTEM_WINDOWS)
// The Visual C++ version of gl.h uses WINGDIAPI and APIENTRY but doesn't define them
#ifdef _MSC_VER
#ifndef WIN32_LEAN_AND_MEAN
#define WIN32_LEAN_AND_MEAN
#endif
#include <windows.h>
#endif
#include <GL/gl.h>
#elif defined(SFML_SYSTEM_LINUX) || defined(SFML_SYSTEM_FREEBSD) || defined(SFML_SYSTEM_OPENBSD) || \
defined(SFML_SYSTEM_NETBSD)
#if defined(SFML_OPENGL_ES)
#include <GLES/gl.h>
#include <GLES/glext.h>
#else
#include <GL/gl.h>
#endif
#elif defined(SFML_SYSTEM_MACOS)
#include <OpenGL/gl.h>
#elif defined(SFML_SYSTEM_IOS)
#include <OpenGLES/ES1/gl.h>
#include <OpenGLES/ES1/glext.h>
#elif defined(SFML_SYSTEM_ANDROID)
#include <GLES/gl.h>
#include <GLES/glext.h>
// We're not using OpenGL ES 2+ yet, but we can use the sRGB extension
#include <GLES2/gl2ext.h>
#include <GLES2/gl2platform.h>
#endif

View File

@ -1,55 +0,0 @@
////////////////////////////////////////////////////////////
//
// SFML - Simple and Fast Multimedia Library
// Copyright (C) 2007-2025 Laurent Gomila (laurent@sfml-dev.org)
//
// This software is provided 'as-is', without any express or implied warranty.
// In no event will the authors be held liable for any damages arising from the use of this software.
//
// Permission is granted to anyone to use this software for any purpose,
// including commercial applications, and to alter it and redistribute it freely,
// subject to the following restrictions:
//
// 1. The origin of this software must not be misrepresented;
// you must not claim that you wrote the original software.
// If you use this software in a product, an acknowledgment
// in the product documentation would be appreciated but is not required.
//
// 2. Altered source versions must be plainly marked as such,
// and must not be misrepresented as being the original software.
//
// 3. This notice may not be removed or altered from any source distribution.
//
////////////////////////////////////////////////////////////
#pragma once
////////////////////////////////////////////////////////////
// Headers
////////////////////////////////////////////////////////////
#include <SFML/Config.hpp>
#include <SFML/System/Angle.hpp>
#include <SFML/System/Clock.hpp>
#include <SFML/System/Err.hpp>
#include <SFML/System/Exception.hpp>
#include <SFML/System/FileInputStream.hpp>
#include <SFML/System/InputStream.hpp>
#include <SFML/System/MemoryInputStream.hpp>
#include <SFML/System/Sleep.hpp>
#include <SFML/System/String.hpp>
#include <SFML/System/Time.hpp>
#include <SFML/System/Utf.hpp>
#include <SFML/System/Vector2.hpp>
#include <SFML/System/Vector3.hpp>
////////////////////////////////////////////////////////////
/// \defgroup system System module
///
/// Base module of SFML, defining various utilities. It provides
/// vector classes, Unicode strings and conversion functions,
/// threads and mutexes, timing classes.
///
////////////////////////////////////////////////////////////

View File

@ -1,511 +0,0 @@
////////////////////////////////////////////////////////////
//
// SFML - Simple and Fast Multimedia Library
// Copyright (C) 2007-2025 Laurent Gomila (laurent@sfml-dev.org)
//
// This software is provided 'as-is', without any express or implied warranty.
// In no event will the authors be held liable for any damages arising from the use of this software.
//
// Permission is granted to anyone to use this software for any purpose,
// including commercial applications, and to alter it and redistribute it freely,
// subject to the following restrictions:
//
// 1. The origin of this software must not be misrepresented;
// you must not claim that you wrote the original software.
// If you use this software in a product, an acknowledgment
// in the product documentation would be appreciated but is not required.
//
// 2. Altered source versions must be plainly marked as such,
// and must not be misrepresented as being the original software.
//
// 3. This notice may not be removed or altered from any source distribution.
//
////////////////////////////////////////////////////////////
#pragma once
namespace sf
{
////////////////////////////////////////////////////////////
/// \brief Represents an angle value.
///
////////////////////////////////////////////////////////////
class Angle
{
public:
////////////////////////////////////////////////////////////
/// \brief Default constructor
///
/// Sets the angle value to zero.
///
////////////////////////////////////////////////////////////
constexpr Angle() = default;
////////////////////////////////////////////////////////////
/// \brief Return the angle's value in degrees
///
/// \return Angle in degrees
///
/// \see `asRadians`
///
////////////////////////////////////////////////////////////
[[nodiscard]] constexpr float asDegrees() const;
////////////////////////////////////////////////////////////
/// \brief Return the angle's value in radians
///
/// \return Angle in radians
///
/// \see `asDegrees`
///
////////////////////////////////////////////////////////////
[[nodiscard]] constexpr float asRadians() const;
////////////////////////////////////////////////////////////
/// \brief Wrap to a range such that -180° <= angle < 180°
///
/// Similar to a modulo operation, this returns a copy of the angle
/// constrained to the range [-180°, 180°) == [-Pi, Pi).
/// The resulting angle represents a rotation which is equivalent to `*this`.
///
/// The name "signed" originates from the similarity to signed integers:
/// <table>
/// <tr>
/// <th></th>
/// <th>signed</th>
/// <th>unsigned</th>
/// </tr>
/// <tr>
/// <td>char</td>
/// <td>[-128, 128)</td>
/// <td>[0, 256)</td>
/// </tr>
/// <tr>
/// <td>Angle</td>
/// <td>[-180°, 180°)</td>
/// <td>[0°, 360°)</td>
/// </tr>
/// </table>
///
/// \return Signed angle, wrapped to [-180°, 180°)
///
/// \see `wrapUnsigned`
///
////////////////////////////////////////////////////////////
[[nodiscard]] constexpr Angle wrapSigned() const;
////////////////////////////////////////////////////////////
/// \brief Wrap to a range such that 0° <= angle < 360°
///
/// Similar to a modulo operation, this returns a copy of the angle
/// constrained to the range [0°, 360°) == [0, Tau) == [0, 2*Pi).
/// The resulting angle represents a rotation which is equivalent to `*this`.
///
/// The name "unsigned" originates from the similarity to unsigned integers:
/// <table>
/// <tr>
/// <th></th>
/// <th>signed</th>
/// <th>unsigned</th>
/// </tr>
/// <tr>
/// <td>char</td>
/// <td>[-128, 128)</td>
/// <td>[0, 256)</td>
/// </tr>
/// <tr>
/// <td>Angle</td>
/// <td>[-180°, 180°)</td>
/// <td>[0°, 360°)</td>
/// </tr>
/// </table>
///
/// \return Unsigned angle, wrapped to [0°, 360°)
///
/// \see `wrapSigned`
///
////////////////////////////////////////////////////////////
[[nodiscard]] constexpr Angle wrapUnsigned() const;
////////////////////////////////////////////////////////////
// Static member data
////////////////////////////////////////////////////////////
// NOLINTNEXTLINE(readability-identifier-naming)
static const Angle Zero; //!< Predefined 0 degree angle value
private:
friend constexpr Angle degrees(float angle);
friend constexpr Angle radians(float angle);
////////////////////////////////////////////////////////////
/// \brief Construct from a number of radians
///
/// This function is internal. To construct angle values,
/// use `sf::radians` or `sf::degrees` instead.
///
/// \param radians Angle in radians
///
////////////////////////////////////////////////////////////
constexpr explicit Angle(float radians);
////////////////////////////////////////////////////////////
// Member data
////////////////////////////////////////////////////////////
float m_radians{}; //!< Angle value stored as radians
};
////////////////////////////////////////////////////////////
/// \brief Construct an angle value from a number of degrees
///
/// \param angle Number of degrees
///
/// \return Angle value constructed from the number of degrees
///
/// \see `radians`
///
////////////////////////////////////////////////////////////
[[nodiscard]] constexpr Angle degrees(float angle);
////////////////////////////////////////////////////////////
/// \brief Construct an angle value from a number of radians
///
/// \param angle Number of radians
///
/// \return Angle value constructed from the number of radians
///
/// \see `degrees`
///
////////////////////////////////////////////////////////////
[[nodiscard]] constexpr Angle radians(float angle);
////////////////////////////////////////////////////////////
/// \relates Angle
/// \brief Overload of `operator==` to compare two angle values
/// \note Does not automatically wrap the angle value
///
/// \param left Left operand (an angle)
/// \param right Right operand (an angle)
///
/// \return `true` if both angle values are equal
///
////////////////////////////////////////////////////////////
[[nodiscard]] constexpr bool operator==(Angle left, Angle right);
////////////////////////////////////////////////////////////
/// \relates Angle
/// \brief Overload of `operator!=` to compare two angle values
/// \note Does not automatically wrap the angle value
///
/// \param left Left operand (an angle)
/// \param right Right operand (an angle)
///
/// \return `true` if both angle values are different
///
////////////////////////////////////////////////////////////
[[nodiscard]] constexpr bool operator!=(Angle left, Angle right);
////////////////////////////////////////////////////////////
/// \relates Angle
/// \brief Overload of `operator<` to compare two angle values
/// \note Does not automatically wrap the angle value
///
/// \param left Left operand (an angle)
/// \param right Right operand (an angle)
///
/// \return `true` if \a left is less than \a right
///
////////////////////////////////////////////////////////////
[[nodiscard]] constexpr bool operator<(Angle left, Angle right);
////////////////////////////////////////////////////////////
/// \relates Angle
/// \brief Overload of `operator>` to compare two angle values
/// \note Does not automatically wrap the angle value
///
/// \param left Left operand (an angle)
/// \param right Right operand (an angle)
///
/// \return `true` if \a left is greater than \a right
///
////////////////////////////////////////////////////////////
[[nodiscard]] constexpr bool operator>(Angle left, Angle right);
////////////////////////////////////////////////////////////
/// \relates Angle
/// \brief Overload of `operator<=` to compare two angle values
/// \note Does not automatically wrap the angle value
///
/// \param left Left operand (an angle)
/// \param right Right operand (an angle)
///
/// \return `true` if \a left is less than or equal to \a right
///
////////////////////////////////////////////////////////////
[[nodiscard]] constexpr bool operator<=(Angle left, Angle right);
////////////////////////////////////////////////////////////
/// \relates Angle
/// \brief Overload of `operator>=` to compare two angle values
/// \note Does not automatically wrap the angle value
///
/// \param left Left operand (an angle)
/// \param right Right operand (an angle)
///
/// \return `true` if \a left is greater than or equal to \a right
///
////////////////////////////////////////////////////////////
[[nodiscard]] constexpr bool operator>=(Angle left, Angle right);
////////////////////////////////////////////////////////////
/// \relates Angle
/// \brief Overload of unary `operator-` to negate an angle value.
///
/// Represents a rotation in the opposite direction.
///
/// \param right Right operand (an angle)
///
/// \return Negative of the angle value
///
////////////////////////////////////////////////////////////
[[nodiscard]] constexpr Angle operator-(Angle right);
////////////////////////////////////////////////////////////
/// \relates Angle
/// \brief Overload of binary `operator+` to add two angle values
///
/// \param left Left operand (an angle)
/// \param right Right operand (an angle)
///
/// \return Sum of the two angle values
///
////////////////////////////////////////////////////////////
[[nodiscard]] constexpr Angle operator+(Angle left, Angle right);
////////////////////////////////////////////////////////////
/// \relates Angle
/// \brief Overload of binary `operator+=` to add/assign two angle values
///
/// \param left Left operand (an angle)
/// \param right Right operand (an angle)
///
/// \return Sum of the two angle values
///
////////////////////////////////////////////////////////////
constexpr Angle& operator+=(Angle& left, Angle right);
////////////////////////////////////////////////////////////
/// \relates Angle
/// \brief Overload of binary `operator-` to subtract two angle values
///
/// \param left Left operand (an angle)
/// \param right Right operand (an angle)
///
/// \return Difference of the two angle values
///
////////////////////////////////////////////////////////////
[[nodiscard]] constexpr Angle operator-(Angle left, Angle right);
////////////////////////////////////////////////////////////
/// \relates Angle
/// \brief Overload of binary `operator-=` to subtract/assign two angle values
///
/// \param left Left operand (an angle)
/// \param right Right operand (an angle)
///
/// \return Difference of the two angle values
///
////////////////////////////////////////////////////////////
constexpr Angle& operator-=(Angle& left, Angle right);
////////////////////////////////////////////////////////////
/// \relates Angle
/// \brief Overload of binary `operator*` to scale an angle value
///
/// \param left Left operand (an angle)
/// \param right Right operand (a number)
///
/// \return `left` multiplied by `right`
///
////////////////////////////////////////////////////////////
[[nodiscard]] constexpr Angle operator*(Angle left, float right);
////////////////////////////////////////////////////////////
/// \relates Angle
/// \brief Overload of binary `operator*` to scale an angle value
///
/// \param left Left operand (a number)
/// \param right Right operand (an angle)
///
/// \return `left` multiplied by `right`
///
////////////////////////////////////////////////////////////
[[nodiscard]] constexpr Angle operator*(float left, Angle right);
////////////////////////////////////////////////////////////
/// \relates Angle
/// \brief Overload of binary `operator*=` to scale/assign an angle value
///
/// \param left Left operand (an angle)
/// \param right Right operand (a number)
///
/// \return `left` multiplied by `right`
///
////////////////////////////////////////////////////////////
constexpr Angle& operator*=(Angle& left, float right);
////////////////////////////////////////////////////////////
/// \relates Angle
/// \brief Overload of binary `operator/` to scale an angle value
///
/// \param left Left operand (an angle)
/// \param right Right operand (a number)
///
/// \return `left` divided by `right`
///
////////////////////////////////////////////////////////////
[[nodiscard]] constexpr Angle operator/(Angle left, float right);
////////////////////////////////////////////////////////////
/// \relates Angle
/// \brief Overload of binary `operator/=` to scale/assign an angle value
///
/// \param left Left operand (an angle)
/// \param right Right operand (a number)
///
/// \return `left` divided by `right`
///
////////////////////////////////////////////////////////////
constexpr Angle& operator/=(Angle& left, float right);
////////////////////////////////////////////////////////////
/// \relates Angle
/// \brief Overload of binary `operator/` to compute the ratio of two angle values
///
/// \param left Left operand (an angle)
/// \param right Right operand (an angle)
///
/// \return `left` divided by `right`
///
////////////////////////////////////////////////////////////
[[nodiscard]] constexpr float operator/(Angle left, Angle right);
////////////////////////////////////////////////////////////
/// \relates Angle
/// \brief Overload of binary `operator%` to compute modulo of an angle value.
///
/// Right hand angle must be greater than zero.
///
/// Examples:
/// \code
/// sf::degrees(90) % sf::degrees(40) // 10 degrees
/// sf::degrees(-90) % sf::degrees(40) // 30 degrees (not -10)
/// \endcode
///
/// \param left Left operand (an angle)
/// \param right Right operand (an angle)
///
/// \return `left` modulo `right`
///
////////////////////////////////////////////////////////////
[[nodiscard]] constexpr Angle operator%(Angle left, Angle right);
////////////////////////////////////////////////////////////
/// \relates Angle
/// \brief Overload of binary `operator%=` to compute/assign remainder of an angle value
///
/// \param left Left operand (an angle)
/// \param right Right operand (an angle)
///
/// \return `left` modulo `right`
///
////////////////////////////////////////////////////////////
constexpr Angle& operator%=(Angle& left, Angle right);
namespace Literals
{
////////////////////////////////////////////////////////////
/// \relates sf::Angle
/// \brief User defined literal for angles in degrees, e.g.\ `10.5_deg`
///
/// \param angle Angle in degrees
///
/// \return Angle
///
////////////////////////////////////////////////////////////
[[nodiscard]] constexpr Angle operator""_deg(long double angle);
////////////////////////////////////////////////////////////
/// \relates sf::Angle
/// \brief User defined literal for angles in degrees, e.g.\ `90_deg`
///
/// \param angle Angle in degrees
///
/// \return Angle
///
////////////////////////////////////////////////////////////
[[nodiscard]] constexpr Angle operator""_deg(unsigned long long int angle);
////////////////////////////////////////////////////////////
/// \relates sf::Angle
/// \brief User defined literal for angles in radians, e.g.\ `0.1_rad`
///
/// \param angle Angle in radians
///
/// \return Angle
///
////////////////////////////////////////////////////////////
[[nodiscard]] constexpr Angle operator""_rad(long double angle);
////////////////////////////////////////////////////////////
/// \relates sf::Angle
/// \brief User defined literal for angles in radians, e.g.\ `2_rad`
///
/// \param angle Angle in radians
///
/// \return Angle
///
////////////////////////////////////////////////////////////
[[nodiscard]] constexpr Angle operator""_rad(unsigned long long int angle);
} // namespace Literals
} // namespace sf
#include <SFML/System/Angle.inl>
////////////////////////////////////////////////////////////
/// \class sf::Angle
/// \ingroup system
///
/// `sf::Angle` encapsulates an angle value in a flexible way.
/// It allows for defining an angle value either as a number
/// of degrees or radians. It also works the other way
/// around. You can read an angle value as either a number
/// of degrees or radians.
///
/// By using such a flexible interface, the API doesn't
/// impose any fixed type or unit for angle values and lets
/// the user choose their own preferred representation.
///
/// Angle values support the usual mathematical operations.
/// You can add or subtract two angles, multiply or divide
/// an angle by a number, compare two angles, etc.
///
/// Usage example:
/// \code
/// sf::Angle a1 = sf::degrees(90);
/// float radians = a1.asRadians(); // 1.5708f
///
/// sf::Angle a2 = sf::radians(3.141592654f);
/// float degrees = a2.asDegrees(); // 180.0f
///
/// using namespace sf::Literals;
/// sf::Angle a3 = 10_deg; // 10 degrees
/// sf::Angle a4 = 1.5_deg; // 1.5 degrees
/// sf::Angle a5 = 1_rad; // 1 radians
/// sf::Angle a6 = 3.14_rad; // 3.14 radians
/// \endcode
///
////////////////////////////////////////////////////////////

View File

@ -1,274 +0,0 @@
////////////////////////////////////////////////////////////
//
// SFML - Simple and Fast Multimedia Library
// Copyright (C) 2007-2025 Laurent Gomila (laurent@sfml-dev.org)
//
// This software is provided 'as-is', without any express or implied warranty.
// In no event will the authors be held liable for any damages arising from the use of this software.
//
// Permission is granted to anyone to use this software for any purpose,
// including commercial applications, and to alter it and redistribute it freely,
// subject to the following restrictions:
//
// 1. The origin of this software must not be misrepresented;
// you must not claim that you wrote the original software.
// If you use this software in a product, an acknowledgment
// in the product documentation would be appreciated but is not required.
//
// 2. Altered source versions must be plainly marked as such,
// and must not be misrepresented as being the original software.
//
// 3. This notice may not be removed or altered from any source distribution.
//
////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////
// Headers
////////////////////////////////////////////////////////////
#include <SFML/System/Angle.hpp> // NOLINT(misc-header-include-cycle)
#include <cassert>
namespace sf
{
namespace priv
{
inline constexpr float pi = 3.141592654f;
inline constexpr float tau = pi * 2.f;
constexpr float positiveRemainder(float a, float b)
{
assert(b > 0.f && "Cannot calculate remainder with non-positive divisor");
const float val = a - static_cast<float>(static_cast<int>(a / b)) * b;
return val >= 0.f ? val : val + b;
}
} // namespace priv
////////////////////////////////////////////////////////////
constexpr float Angle::asDegrees() const
{
return m_radians * (180.f / priv::pi);
}
////////////////////////////////////////////////////////////
constexpr float Angle::asRadians() const
{
return m_radians;
}
////////////////////////////////////////////////////////////
constexpr Angle Angle::wrapSigned() const
{
return radians(priv::positiveRemainder(m_radians + priv::pi, priv::tau) - priv::pi);
}
////////////////////////////////////////////////////////////
constexpr Angle Angle::wrapUnsigned() const
{
return radians(priv::positiveRemainder(m_radians, priv::tau));
}
////////////////////////////////////////////////////////////
constexpr Angle::Angle(float radians) : m_radians(radians)
{
}
////////////////////////////////////////////////////////////
constexpr Angle degrees(float angle)
{
return Angle(angle * (priv::pi / 180.f));
}
////////////////////////////////////////////////////////////
constexpr Angle radians(float angle)
{
return Angle(angle);
}
////////////////////////////////////////////////////////////
constexpr bool operator==(Angle left, Angle right)
{
return left.asRadians() == right.asRadians();
}
////////////////////////////////////////////////////////////
constexpr bool operator!=(Angle left, Angle right)
{
return left.asRadians() != right.asRadians();
}
////////////////////////////////////////////////////////////
constexpr bool operator<(Angle left, Angle right)
{
return left.asRadians() < right.asRadians();
}
////////////////////////////////////////////////////////////
constexpr bool operator>(Angle left, Angle right)
{
return left.asRadians() > right.asRadians();
}
////////////////////////////////////////////////////////////
constexpr bool operator<=(Angle left, Angle right)
{
return left.asRadians() <= right.asRadians();
}
////////////////////////////////////////////////////////////
constexpr bool operator>=(Angle left, Angle right)
{
return left.asRadians() >= right.asRadians();
}
////////////////////////////////////////////////////////////
constexpr Angle operator-(Angle right)
{
return radians(-right.asRadians());
}
////////////////////////////////////////////////////////////
constexpr Angle operator+(Angle left, Angle right)
{
return radians(left.asRadians() + right.asRadians());
}
////////////////////////////////////////////////////////////
constexpr Angle& operator+=(Angle& left, Angle right)
{
return left = left + right;
}
////////////////////////////////////////////////////////////
constexpr Angle operator-(Angle left, Angle right)
{
return radians(left.asRadians() - right.asRadians());
}
////////////////////////////////////////////////////////////
constexpr Angle& operator-=(Angle& left, Angle right)
{
return left = left - right;
}
////////////////////////////////////////////////////////////
constexpr Angle operator*(Angle left, float right)
{
return radians(left.asRadians() * right);
}
////////////////////////////////////////////////////////////
constexpr Angle operator*(float left, Angle right)
{
return right * left;
}
////////////////////////////////////////////////////////////
constexpr Angle& operator*=(Angle& left, float right)
{
return left = left * right;
}
////////////////////////////////////////////////////////////
constexpr Angle operator/(Angle left, float right)
{
assert(right != 0.f && "Angle::operator/ cannot divide by 0");
return radians(left.asRadians() / right);
}
////////////////////////////////////////////////////////////
constexpr Angle& operator/=(Angle& left, float right)
{
assert(right != 0.f && "Angle::operator/= cannot divide by 0");
return left = left / right;
}
////////////////////////////////////////////////////////////
constexpr float operator/(Angle left, Angle right)
{
assert(right.asRadians() != 0.f && "Angle::operator/ cannot divide by 0");
return left.asRadians() / right.asRadians();
}
////////////////////////////////////////////////////////////
constexpr Angle operator%(Angle left, Angle right)
{
assert(right.asRadians() != 0.f && "Angle::operator% cannot modulus by 0");
return radians(priv::positiveRemainder(left.asRadians(), right.asRadians()));
}
////////////////////////////////////////////////////////////
constexpr Angle& operator%=(Angle& left, Angle right)
{
assert(right.asRadians() != 0.f && "Angle::operator%= cannot modulus by 0");
return left = left % right;
}
namespace Literals
{
////////////////////////////////////////////////////////////
constexpr Angle operator""_deg(long double angle)
{
return degrees(static_cast<float>(angle));
}
////////////////////////////////////////////////////////////
constexpr Angle operator""_deg(unsigned long long angle)
{
return degrees(static_cast<float>(angle));
}
////////////////////////////////////////////////////////////
constexpr Angle operator""_rad(long double angle)
{
return radians(static_cast<float>(angle));
}
////////////////////////////////////////////////////////////
constexpr Angle operator""_rad(unsigned long long angle)
{
return radians(static_cast<float>(angle));
}
} // namespace Literals
////////////////////////////////////////////////////////////
// Static member data
////////////////////////////////////////////////////////////
// Note: the 'inline' keyword here is technically not required, but VS2019 fails
// to compile with a bogus "multiple definition" error if not explicitly used.
inline constexpr Angle Angle::Zero;
} // namespace sf

View File

@ -1,196 +0,0 @@
////////////////////////////////////////////////////////////
//
// SFML - Simple and Fast Multimedia Library
// Copyright (C) 2007-2025 Laurent Gomila (laurent@sfml-dev.org)
//
// This software is provided 'as-is', without any express or implied warranty.
// In no event will the authors be held liable for any damages arising from the use of this software.
//
// Permission is granted to anyone to use this software for any purpose,
// including commercial applications, and to alter it and redistribute it freely,
// subject to the following restrictions:
//
// 1. The origin of this software must not be misrepresented;
// you must not claim that you wrote the original software.
// If you use this software in a product, an acknowledgment
// in the product documentation would be appreciated but is not required.
//
// 2. Altered source versions must be plainly marked as such,
// and must not be misrepresented as being the original software.
//
// 3. This notice may not be removed or altered from any source distribution.
//
////////////////////////////////////////////////////////////
#pragma once
////////////////////////////////////////////////////////////
// Headers
////////////////////////////////////////////////////////////
#include <SFML/System/Export.hpp>
#include <chrono>
#include <ratio>
#include <type_traits>
#ifdef SFML_SYSTEM_ANDROID
#include <SFML/System/SuspendAwareClock.hpp>
#endif
namespace sf
{
namespace priv
{
////////////////////////////////////////////////////////////
/// \brief Chooses a monotonic clock of highest resolution
///
/// The `high_resolution_clock` is usually an alias for other
/// clocks: `steady_clock` or `system_clock`, whichever has a
/// higher precision.
///
/// `sf::Clock`, however, is aimed towards monotonic time
/// measurements and so `system_clock` could never be a choice
/// as its subject to discontinuous jumps in the system time
/// (e.g., if the system administrator manually changes
/// the clock), and by the incremental adjustments performed
/// by `adjtime` and Network Time Protocol. On the other
/// hand, monotonic clocks are unaffected by this behavior.
///
/// Note: Linux implementation of a monotonic clock that
/// takes sleep time into account is represented by
/// `CLOCK_BOOTTIME`. Android devices can define the macro:
/// `SFML_ANDROID_USE_SUSPEND_AWARE_CLOCK` to use a separate
/// implementation of that clock, instead.
///
/// For more information on Linux clocks visit:
/// https://linux.die.net/man/2/clock_gettime
///
////////////////////////////////////////////////////////////
#if defined(SFML_SYSTEM_ANDROID) && defined(SFML_ANDROID_USE_SUSPEND_AWARE_CLOCK)
using ClockImpl = SuspendAwareClock;
#else
using ClockImpl = std::conditional_t<std::chrono::high_resolution_clock::is_steady, std::chrono::high_resolution_clock, std::chrono::steady_clock>;
#endif
static_assert(ClockImpl::is_steady, "Provided implementation is not a monotonic clock");
static_assert(std::ratio_less_equal_v<ClockImpl::period, std::micro>,
"Clock resolution is too low. Expecting at least a microsecond precision");
} // namespace priv
class Time;
////////////////////////////////////////////////////////////
/// \brief Utility class that measures the elapsed time
///
/// The clock starts automatically after being constructed.
///
////////////////////////////////////////////////////////////
class SFML_SYSTEM_API Clock
{
public:
////////////////////////////////////////////////////////////
/// \brief Get the elapsed time
///
/// This function returns the time elapsed since the last call
/// to `restart()` (or the construction of the instance if `restart()`
/// has not been called).
///
/// \return Time elapsed
///
////////////////////////////////////////////////////////////
[[nodiscard]] Time getElapsedTime() const;
////////////////////////////////////////////////////////////
/// \brief Check whether the clock is running
///
/// \return `true` if the clock is running, `false` otherwise
///
////////////////////////////////////////////////////////////
[[nodiscard]] bool isRunning() const;
////////////////////////////////////////////////////////////
/// \brief Start the clock
///
/// \see `stop`
///
////////////////////////////////////////////////////////////
void start();
////////////////////////////////////////////////////////////
/// \brief Stop the clock
///
/// \see `start`
///
////////////////////////////////////////////////////////////
void stop();
////////////////////////////////////////////////////////////
/// \brief Restart the clock
///
/// This function puts the time counter back to zero, returns
/// the elapsed time, and leaves the clock in a running state.
///
/// \return Time elapsed
///
/// \see `reset`
///
////////////////////////////////////////////////////////////
Time restart();
////////////////////////////////////////////////////////////
/// \brief Reset the clock
///
/// This function puts the time counter back to zero, returns
/// the elapsed time, and leaves the clock in a paused state.
///
/// \return Time elapsed
///
/// \see `restart`
///
////////////////////////////////////////////////////////////
Time reset();
private:
////////////////////////////////////////////////////////////
// Member data
////////////////////////////////////////////////////////////
priv::ClockImpl::time_point m_refPoint{priv::ClockImpl::now()}; //!< Time of last reset
priv::ClockImpl::time_point m_stopPoint; //!< Time of last stop
};
} // namespace sf
////////////////////////////////////////////////////////////
/// \class sf::Clock
/// \ingroup system
///
/// `sf::Clock` is a lightweight class for measuring time.
///
/// It provides the most precise time that the underlying
/// OS can achieve (generally microseconds or nanoseconds).
/// It also ensures monotonicity, which means that the returned
/// time can never go backward, even if the system time is
/// changed.
///
/// Usage example:
/// \code
/// sf::Clock clock;
/// ...
/// Time time1 = clock.getElapsedTime();
/// ...
/// Time time2 = clock.restart();
/// ...
/// Time time3 = clock.reset();
/// \endcode
///
/// The `sf::Time` value returned by the clock can then be
/// converted to a number of seconds, milliseconds or even
/// microseconds.
///
/// \see `sf::Time`
///
////////////////////////////////////////////////////////////

View File

@ -1,77 +0,0 @@
////////////////////////////////////////////////////////////
//
// SFML - Simple and Fast Multimedia Library
// Copyright (C) 2007-2025 Laurent Gomila (laurent@sfml-dev.org)
//
// This software is provided 'as-is', without any express or implied warranty.
// In no event will the authors be held liable for any damages arising from the use of this software.
//
// Permission is granted to anyone to use this software for any purpose,
// including commercial applications, and to alter it and redistribute it freely,
// subject to the following restrictions:
//
// 1. The origin of this software must not be misrepresented;
// you must not claim that you wrote the original software.
// If you use this software in a product, an acknowledgment
// in the product documentation would be appreciated but is not required.
//
// 2. Altered source versions must be plainly marked as such,
// and must not be misrepresented as being the original software.
//
// 3. This notice may not be removed or altered from any source distribution.
//
////////////////////////////////////////////////////////////
#pragma once
////////////////////////////////////////////////////////////
// Headers
////////////////////////////////////////////////////////////
#include <SFML/System/Export.hpp>
#include <iosfwd>
namespace sf
{
////////////////////////////////////////////////////////////
/// \brief Standard stream used by SFML to output warnings and errors
///
////////////////////////////////////////////////////////////
[[nodiscard]] SFML_SYSTEM_API std::ostream& err();
} // namespace sf
////////////////////////////////////////////////////////////
/// \fn sf::err
/// \ingroup system
///
/// By default, `sf::err()` outputs to the same location as `std::cerr`,
/// (-> the stderr descriptor) which is the console if there's
/// one available.
///
/// It is a standard `std::ostream` instance, so it supports all the
/// insertion operations defined by the STL
/// (`operator<<`, manipulators, etc.).
///
/// `sf::err()` can be redirected to write to another output, independently
/// of `std::cerr`, by using the `rdbuf()` function provided by the
/// `std::ostream` class.
///
/// Example:
/// \code
/// // Redirect to a file
/// std::ofstream file("sfml-log.txt");
/// std::streambuf* previous = sf::err().rdbuf(file.rdbuf());
///
/// // Redirect to nothing
/// sf::err().rdbuf(nullptr);
///
/// // Restore the original output
/// sf::err().rdbuf(previous);
/// \endcode
///
/// \return Reference to `std::ostream` representing the SFML error stream
///
////////////////////////////////////////////////////////////

View File

@ -1,46 +0,0 @@
////////////////////////////////////////////////////////////
//
// SFML - Simple and Fast Multimedia Library
// Copyright (C) 2007-2025 Laurent Gomila (laurent@sfml-dev.org)
//
// This software is provided 'as-is', without any express or implied warranty.
// In no event will the authors be held liable for any damages arising from the use of this software.
//
// Permission is granted to anyone to use this software for any purpose,
// including commercial applications, and to alter it and redistribute it freely,
// subject to the following restrictions:
//
// 1. The origin of this software must not be misrepresented;
// you must not claim that you wrote the original software.
// If you use this software in a product, an acknowledgment
// in the product documentation would be appreciated but is not required.
//
// 2. Altered source versions must be plainly marked as such,
// and must not be misrepresented as being the original software.
//
// 3. This notice may not be removed or altered from any source distribution.
//
////////////////////////////////////////////////////////////
#pragma once
////////////////////////////////////////////////////////////
// Headers
////////////////////////////////////////////////////////////
#include <SFML/System/Export.hpp>
#include <stdexcept>
namespace sf
{
////////////////////////////////////////////////////////////
/// \brief Library-specific exception type
///
////////////////////////////////////////////////////////////
class SFML_SYSTEM_API Exception : public std::runtime_error
{
public:
using std::runtime_error::runtime_error;
};
} // namespace sf

View File

@ -1,44 +0,0 @@
////////////////////////////////////////////////////////////
//
// SFML - Simple and Fast Multimedia Library
// Copyright (C) 2007-2025 Laurent Gomila (laurent@sfml-dev.org)
//
// This software is provided 'as-is', without any express or implied warranty.
// In no event will the authors be held liable for any damages arising from the use of this software.
//
// Permission is granted to anyone to use this software for any purpose,
// including commercial applications, and to alter it and redistribute it freely,
// subject to the following restrictions:
//
// 1. The origin of this software must not be misrepresented;
// you must not claim that you wrote the original software.
// If you use this software in a product, an acknowledgment
// in the product documentation would be appreciated but is not required.
//
// 2. Altered source versions must be plainly marked as such,
// and must not be misrepresented as being the original software.
//
// 3. This notice may not be removed or altered from any source distribution.
//
////////////////////////////////////////////////////////////
#pragma once
////////////////////////////////////////////////////////////
// Headers
////////////////////////////////////////////////////////////
#include <SFML/Config.hpp>
////////////////////////////////////////////////////////////
// Portable import / export macros
////////////////////////////////////////////////////////////
#if defined(SFML_SYSTEM_EXPORTS)
#define SFML_SYSTEM_API SFML_API_EXPORT
#else
#define SFML_SYSTEM_API SFML_API_IMPORT
#endif

View File

@ -1,212 +0,0 @@
////////////////////////////////////////////////////////////
//
// SFML - Simple and Fast Multimedia Library
// Copyright (C) 2007-2025 Laurent Gomila (laurent@sfml-dev.org)
//
// This software is provided 'as-is', without any express or implied warranty.
// In no event will the authors be held liable for any damages arising from the use of this software.
//
// Permission is granted to anyone to use this software for any purpose,
// including commercial applications, and to alter it and redistribute it freely,
// subject to the following restrictions:
//
// 1. The origin of this software must not be misrepresented;
// you must not claim that you wrote the original software.
// If you use this software in a product, an acknowledgment
// in the product documentation would be appreciated but is not required.
//
// 2. Altered source versions must be plainly marked as such,
// and must not be misrepresented as being the original software.
//
// 3. This notice may not be removed or altered from any source distribution.
//
////////////////////////////////////////////////////////////
#pragma once
////////////////////////////////////////////////////////////
// Headers
////////////////////////////////////////////////////////////
#include <SFML/Config.hpp>
#include <SFML/System/Export.hpp>
#include <SFML/System/InputStream.hpp>
#include <filesystem>
#include <memory>
#include <cstdint>
#include <cstdio>
#ifdef SFML_SYSTEM_ANDROID
namespace sf::priv
{
class SFML_SYSTEM_API ResourceStream;
}
#endif
namespace sf
{
////////////////////////////////////////////////////////////
/// \brief Implementation of input stream based on a file
///
////////////////////////////////////////////////////////////
class SFML_SYSTEM_API FileInputStream : public InputStream
{
public:
////////////////////////////////////////////////////////////
/// \brief Default constructor
///
/// Construct a file input stream that is not associated
/// with a file to read.
///
////////////////////////////////////////////////////////////
FileInputStream();
////////////////////////////////////////////////////////////
/// \brief Default destructor
///
////////////////////////////////////////////////////////////
~FileInputStream() override;
////////////////////////////////////////////////////////////
/// \brief Deleted copy constructor
///
////////////////////////////////////////////////////////////
FileInputStream(const FileInputStream&) = delete;
////////////////////////////////////////////////////////////
/// \brief Deleted copy assignment
///
////////////////////////////////////////////////////////////
FileInputStream& operator=(const FileInputStream&) = delete;
////////////////////////////////////////////////////////////
/// \brief Move constructor
///
////////////////////////////////////////////////////////////
FileInputStream(FileInputStream&&) noexcept;
////////////////////////////////////////////////////////////
/// \brief Move assignment
///
////////////////////////////////////////////////////////////
FileInputStream& operator=(FileInputStream&&) noexcept;
////////////////////////////////////////////////////////////
/// \brief Construct the stream from a file path
///
/// \param filename Name of the file to open
///
/// \throws sf::Exception on error
///
////////////////////////////////////////////////////////////
explicit FileInputStream(const std::filesystem::path& filename);
////////////////////////////////////////////////////////////
/// \brief Open the stream from a file path
///
/// \param filename Name of the file to open
///
/// \return `true` on success, `false` on error
///
////////////////////////////////////////////////////////////
[[nodiscard]] bool open(const std::filesystem::path& filename);
////////////////////////////////////////////////////////////
/// \brief Read data from the stream
///
/// After reading, the stream's reading position must be
/// advanced by the amount of bytes read.
///
/// \param data Buffer where to copy the read data
/// \param size Desired number of bytes to read
///
/// \return The number of bytes actually read, or `std::nullopt` on error
///
////////////////////////////////////////////////////////////
[[nodiscard]] std::optional<std::size_t> read(void* data, std::size_t size) override;
////////////////////////////////////////////////////////////
/// \brief Change the current reading position
///
/// \param position The position to seek to, from the beginning
///
/// \return The position actually sought to, or `std::nullopt` on error
///
////////////////////////////////////////////////////////////
[[nodiscard]] std::optional<std::size_t> seek(std::size_t position) override;
////////////////////////////////////////////////////////////
/// \brief Get the current reading position in the stream
///
/// \return The current position, or `std::nullopt` on error.
///
////////////////////////////////////////////////////////////
[[nodiscard]] std::optional<std::size_t> tell() override;
////////////////////////////////////////////////////////////
/// \brief Return the size of the stream
///
/// \return The total number of bytes available in the stream, or `std::nullopt` on error
///
////////////////////////////////////////////////////////////
std::optional<std::size_t> getSize() override;
private:
////////////////////////////////////////////////////////////
/// \brief Deleter for stdio file stream that closes the file stream
///
////////////////////////////////////////////////////////////
struct FileCloser
{
void operator()(std::FILE* file);
};
////////////////////////////////////////////////////////////
// Member data
////////////////////////////////////////////////////////////
#ifdef SFML_SYSTEM_ANDROID
std::unique_ptr<priv::ResourceStream> m_androidFile;
#endif
std::unique_ptr<std::FILE, FileCloser> m_file; //!< stdio file stream
};
} // namespace sf
////////////////////////////////////////////////////////////
/// \class sf::FileInputStream
/// \ingroup system
///
/// This class is a specialization of `InputStream` that
/// reads from a file on disk.
///
/// It wraps a file in the common `InputStream` interface
/// and therefore allows to use generic classes or functions
/// that accept such a stream, with a file on disk as the data
/// source.
///
/// In addition to the virtual functions inherited from
/// `InputStream`, `FileInputStream` adds a function to
/// specify the file to open.
///
/// SFML resource classes can usually be loaded directly from
/// a filename, so this class shouldn't be useful to you unless
/// you create your own algorithms that operate on an InputStream.
///
/// Usage example:
/// \code
/// void process(InputStream& stream);
///
/// std::optional stream = sf::FileInputStream::open("some_file.dat");
/// if (stream)
/// process(*stream);
/// \endcode
///
/// \see `InputStream`, `MemoryInputStream`
///
////////////////////////////////////////////////////////////

View File

@ -1,166 +0,0 @@
////////////////////////////////////////////////////////////
//
// SFML - Simple and Fast Multimedia Library
// Copyright (C) 2007-2025 Laurent Gomila (laurent@sfml-dev.org)
//
// This software is provided 'as-is', without any express or implied warranty.
// In no event will the authors be held liable for any damages arising from the use of this software.
//
// Permission is granted to anyone to use this software for any purpose,
// including commercial applications, and to alter it and redistribute it freely,
// subject to the following restrictions:
//
// 1. The origin of this software must not be misrepresented;
// you must not claim that you wrote the original software.
// If you use this software in a product, an acknowledgment
// in the product documentation would be appreciated but is not required.
//
// 2. Altered source versions must be plainly marked as such,
// and must not be misrepresented as being the original software.
//
// 3. This notice may not be removed or altered from any source distribution.
//
////////////////////////////////////////////////////////////
#pragma once
////////////////////////////////////////////////////////////
// Headers
////////////////////////////////////////////////////////////
#include <SFML/Config.hpp>
#include <SFML/System/Export.hpp>
#include <optional>
#include <cstdint>
namespace sf
{
////////////////////////////////////////////////////////////
/// \brief Abstract class for custom file input streams
///
////////////////////////////////////////////////////////////
class SFML_SYSTEM_API InputStream
{
public:
////////////////////////////////////////////////////////////
/// \brief Virtual destructor
///
////////////////////////////////////////////////////////////
virtual ~InputStream() = default;
////////////////////////////////////////////////////////////
/// \brief Read data from the stream
///
/// After reading, the stream's reading position must be
/// advanced by the amount of bytes read.
///
/// \param data Buffer where to copy the read data
/// \param size Desired number of bytes to read
///
/// \return The number of bytes actually read, or `std::nullopt` on error
///
////////////////////////////////////////////////////////////
[[nodiscard]] virtual std::optional<std::size_t> read(void* data, std::size_t size) = 0;
////////////////////////////////////////////////////////////
/// \brief Change the current reading position
///
/// \param position The position to seek to, from the beginning
///
/// \return The position actually sought to, or `std::nullopt` on error
///
////////////////////////////////////////////////////////////
[[nodiscard]] virtual std::optional<std::size_t> seek(std::size_t position) = 0;
////////////////////////////////////////////////////////////
/// \brief Get the current reading position in the stream
///
/// \return The current position, or `std::nullopt` on error.
///
////////////////////////////////////////////////////////////
[[nodiscard]] virtual std::optional<std::size_t> tell() = 0;
////////////////////////////////////////////////////////////
/// \brief Return the size of the stream
///
/// \return The total number of bytes available in the stream, or `std::nullopt` on error
///
////////////////////////////////////////////////////////////
virtual std::optional<std::size_t> getSize() = 0;
};
} // namespace sf
////////////////////////////////////////////////////////////
/// \class sf::InputStream
/// \ingroup system
///
/// This class allows users to define their own file input sources
/// from which SFML can load resources.
///
/// SFML resource classes like `sf::Texture` and
/// `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 `loadFromStream` function.
///
/// Usage example:
/// \code
/// // custom stream class that reads from inside a zip file
/// class ZipStream : public sf::InputStream
/// {
/// public:
///
/// ZipStream(const std::string& archive);
///
/// [[nodiscard]] bool open(const std::filesystem::path& filename);
///
/// [[nodiscard]] std::optional<std::size_t> read(void* data, std::size_t size);
///
/// [[nodiscard]] std::optional<std::size_t> seek(std::size_t position);
///
/// [[nodiscard]] std::optional<std::size_t> tell();
///
/// std::optional<std::size_t> getSize();
///
/// private:
///
/// ...
/// };
///
/// // now you can load textures...
/// ZipStream stream("resources.zip");
///
/// if (!stream.open("images/img.png"))
/// {
/// // Handle error...
/// }
///
/// const sf::Texture texture(stream);
///
/// // musics...
/// sf::Music music;
/// ZipStream stream("resources.zip");
///
/// if (!stream.open("musics/msc.ogg"))
/// {
/// // Handle error...
/// }
///
/// if (!music.openFromStream(stream))
/// {
/// // Handle error...
/// }
///
/// // etc.
/// \endcode
///
/// \see `FileInputStream`, `MemoryInputStream`
///
////////////////////////////////////////////////////////////

View File

@ -1,139 +0,0 @@
////////////////////////////////////////////////////////////
//
// SFML - Simple and Fast Multimedia Library
// Copyright (C) 2007-2025 Laurent Gomila (laurent@sfml-dev.org)
//
// This software is provided 'as-is', without any express or implied warranty.
// In no event will the authors be held liable for any damages arising from the use of this software.
//
// Permission is granted to anyone to use this software for any purpose,
// including commercial applications, and to alter it and redistribute it freely,
// subject to the following restrictions:
//
// 1. The origin of this software must not be misrepresented;
// you must not claim that you wrote the original software.
// If you use this software in a product, an acknowledgment
// in the product documentation would be appreciated but is not required.
//
// 2. Altered source versions must be plainly marked as such,
// and must not be misrepresented as being the original software.
//
// 3. This notice may not be removed or altered from any source distribution.
//
////////////////////////////////////////////////////////////
#pragma once
////////////////////////////////////////////////////////////
// Headers
////////////////////////////////////////////////////////////
#include <SFML/Config.hpp>
#include <SFML/System/Export.hpp>
#include <SFML/System/InputStream.hpp>
#include <cstddef>
#include <cstdint>
namespace sf
{
////////////////////////////////////////////////////////////
/// \brief Implementation of input stream based on a memory chunk
///
////////////////////////////////////////////////////////////
class SFML_SYSTEM_API MemoryInputStream : public InputStream
{
public:
////////////////////////////////////////////////////////////
/// \brief Construct the stream from its data
///
/// \param data Pointer to the data in memory
/// \param sizeInBytes Size of the data, in bytes
///
////////////////////////////////////////////////////////////
MemoryInputStream(const void* data, std::size_t sizeInBytes);
////////////////////////////////////////////////////////////
/// \brief Read data from the stream
///
/// After reading, the stream's reading position must be
/// advanced by the amount of bytes read.
///
/// \param data Buffer where to copy the read data
/// \param size Desired number of bytes to read
///
/// \return The number of bytes actually read, or `std::nullopt` on error
///
////////////////////////////////////////////////////////////
[[nodiscard]] std::optional<std::size_t> read(void* data, std::size_t size) override;
////////////////////////////////////////////////////////////
/// \brief Change the current reading position
///
/// \param position The position to seek to, from the beginning
///
/// \return The position actually sought to, or `std::nullopt` on error
///
////////////////////////////////////////////////////////////
[[nodiscard]] std::optional<std::size_t> seek(std::size_t position) override;
////////////////////////////////////////////////////////////
/// \brief Get the current reading position in the stream
///
/// \return The current position, or `std::nullopt` on error.
///
////////////////////////////////////////////////////////////
[[nodiscard]] std::optional<std::size_t> tell() override;
////////////////////////////////////////////////////////////
/// \brief Return the size of the stream
///
/// \return The total number of bytes available in the stream, or `std::nullopt` on error
///
////////////////////////////////////////////////////////////
std::optional<std::size_t> getSize() override;
private:
////////////////////////////////////////////////////////////
// Member data
////////////////////////////////////////////////////////////
const std::byte* m_data{}; //!< Pointer to the data in memory
std::size_t m_size{}; //!< Total size of the data
std::size_t m_offset{}; //!< Current reading position
};
} // namespace sf
////////////////////////////////////////////////////////////
/// \class sf::MemoryInputStream
/// \ingroup system
///
/// This class is a specialization of `InputStream` that
/// reads from data in memory.
///
/// It wraps a memory chunk in the common `InputStream` interface
/// and therefore allows to use generic classes or functions
/// that accept such a stream, with content already loaded in memory.
///
/// In addition to the virtual functions inherited from
/// `InputStream`, `MemoryInputStream` adds a function to
/// specify the pointer and size of the data in memory.
///
/// SFML resource classes can usually be loaded directly from
/// memory, so this class shouldn't be useful to you unless
/// you create your own algorithms that operate on an InputStream.
///
/// Usage example:
/// \code
/// void process(InputStream& stream);
///
/// MemoryInputStream stream(thePtr, theSize);
/// process(stream);
/// \endcode
///
/// \see `InputStream`, `FileInputStream`
///
////////////////////////////////////////////////////////////

View File

@ -1,58 +0,0 @@
////////////////////////////////////////////////////////////
//
// SFML - Simple and Fast Multimedia Library
// Copyright (C) 2007-2025 Laurent Gomila (laurent@sfml-dev.org)
//
// This software is provided 'as-is', without any express or implied warranty.
// In no event will the authors be held liable for any damages arising from the use of this software.
//
// Permission is granted to anyone to use this software for any purpose,
// including commercial applications, and to alter it and redistribute it freely,
// subject to the following restrictions:
//
// 1. The origin of this software must not be misrepresented;
// you must not claim that you wrote the original software.
// If you use this software in a product, an acknowledgment
// in the product documentation would be appreciated but is not required.
//
// 2. Altered source versions must be plainly marked as such,
// and must not be misrepresented as being the original software.
//
// 3. This notice may not be removed or altered from any source distribution.
//
////////////////////////////////////////////////////////////
#pragma once
////////////////////////////////////////////////////////////
// Headers
////////////////////////////////////////////////////////////
#include <SFML/System/Export.hpp>
#if !defined(SFML_SYSTEM_ANDROID)
#error NativeActivity.hpp: This header is Android only.
#endif
struct ANativeActivity;
namespace sf
{
////////////////////////////////////////////////////////////
/// \ingroup system
/// \brief Return a pointer to the Android native activity
///
/// You shouldn't have to use this function, unless you want
/// to implement very specific details, that SFML doesn't
/// support, or to use a workaround for a known issue.
///
/// \return Pointer to Android native activity structure
///
/// \sfplatform{Android,SFML/System/NativeActivity.hpp}
///
////////////////////////////////////////////////////////////
[[nodiscard]] SFML_SYSTEM_API ANativeActivity* getNativeActivity();
} // namespace sf

View File

@ -1,57 +0,0 @@
////////////////////////////////////////////////////////////
//
// SFML - Simple and Fast Multimedia Library
// Copyright (C) 2007-2025 Laurent Gomila (laurent@sfml-dev.org)
//
// This software is provided 'as-is', without any express or implied warranty.
// In no event will the authors be held liable for any damages arising from the use of this software.
//
// Permission is granted to anyone to use this software for any purpose,
// including commercial applications, and to alter it and redistribute it freely,
// subject to the following restrictions:
//
// 1. The origin of this software must not be misrepresented;
// you must not claim that you wrote the original software.
// If you use this software in a product, an acknowledgment
// in the product documentation would be appreciated but is not required.
//
// 2. Altered source versions must be plainly marked as such,
// and must not be misrepresented as being the original software.
//
// 3. This notice may not be removed or altered from any source distribution.
//
////////////////////////////////////////////////////////////
#pragma once
////////////////////////////////////////////////////////////
// Headers
////////////////////////////////////////////////////////////
#include <SFML/System/Export.hpp>
namespace sf
{
class Time;
////////////////////////////////////////////////////////////
/// \ingroup system
/// \brief Make the current thread sleep for a given duration
///
/// `sf::sleep` is the best way to block a program or one of its
/// threads, as it doesn't consume any CPU power. Compared to
/// the standard `std::this_thread::sleep_for` function, this
/// one provides more accurate sleeping time thanks to some
/// platform-specific tweaks.
///
/// `sf::sleep` only guarantees millisecond precision. Sleeping
/// for a duration less than 1 millisecond is prone to result
/// in the actual sleep duration being less than what is
/// requested.
///
/// \param duration Time to sleep
///
////////////////////////////////////////////////////////////
void SFML_SYSTEM_API sleep(Time duration);
} // namespace sf

View File

@ -1,700 +0,0 @@
////////////////////////////////////////////////////////////
//
// SFML - Simple and Fast Multimedia Library
// Copyright (C) 2007-2025 Laurent Gomila (laurent@sfml-dev.org)
//
// This software is provided 'as-is', without any express or implied warranty.
// In no event will the authors be held liable for any damages arising from the use of this software.
//
// Permission is granted to anyone to use this software for any purpose,
// including commercial applications, and to alter it and redistribute it freely,
// subject to the following restrictions:
//
// 1. The origin of this software must not be misrepresented;
// you must not claim that you wrote the original software.
// If you use this software in a product, an acknowledgment
// in the product documentation would be appreciated but is not required.
//
// 2. Altered source versions must be plainly marked as such,
// and must not be misrepresented as being the original software.
//
// 3. This notice may not be removed or altered from any source distribution.
//
////////////////////////////////////////////////////////////
#pragma once
////////////////////////////////////////////////////////////
// Headers
////////////////////////////////////////////////////////////
#include <SFML/System/Export.hpp>
#include <SFML/System/Utf.hpp>
#include <locale>
#include <string>
#include <cstddef>
#include <cstdint>
namespace sf
{
////////////////////////////////////////////////////////////
/// \brief Character traits for `std::uint8_t`
///
////////////////////////////////////////////////////////////
struct SFML_SYSTEM_API U8StringCharTraits
{
// NOLINTBEGIN(readability-identifier-naming)
using char_type = std::uint8_t;
using int_type = std::char_traits<char>::int_type;
using off_type = std::char_traits<char>::off_type;
using pos_type = std::char_traits<char>::pos_type;
using state_type = std::char_traits<char>::state_type;
static void assign(char_type& c1, char_type c2) noexcept;
static char_type* assign(char_type* s, std::size_t n, char_type c);
static bool eq(char_type c1, char_type c2) noexcept;
static bool lt(char_type c1, char_type c2) noexcept;
static char_type* move(char_type* s1, const char_type* s2, std::size_t n);
static char_type* copy(char_type* s1, const char_type* s2, std::size_t n);
static int compare(const char_type* s1, const char_type* s2, std::size_t n);
static std::size_t length(const char_type* s);
static const char_type* find(const char_type* s, std::size_t n, const char_type& c);
static char_type to_char_type(int_type i) noexcept;
static int_type to_int_type(char_type c) noexcept;
static bool eq_int_type(int_type i1, int_type i2) noexcept;
static int_type eof() noexcept;
static int_type not_eof(int_type i) noexcept;
// NOLINTEND(readability-identifier-naming)
};
////////////////////////////////////////////////////////////
/// \brief Portable replacement for `std::basic_string<std::uint8_t>`
///
/// While all major C++ implementations happen to define this
/// as of early 2024, this specialization is not strictly speaking
/// standard C++. Thus we can't depend on its continued existence.
///
////////////////////////////////////////////////////////////
using U8String = std::basic_string<std::uint8_t, U8StringCharTraits>;
////////////////////////////////////////////////////////////
/// \brief Utility string class that automatically handles
/// conversions between types and encodings
///
////////////////////////////////////////////////////////////
class SFML_SYSTEM_API String
{
public:
////////////////////////////////////////////////////////////
// Types
////////////////////////////////////////////////////////////
using Iterator = std::u32string::iterator; //!< Iterator type
using ConstIterator = std::u32string::const_iterator; //!< Read-only iterator type
////////////////////////////////////////////////////////////
// Static member data
////////////////////////////////////////////////////////////
// NOLINTBEGIN(readability-identifier-naming)
/// Represents an invalid position in the string
static inline const std::size_t InvalidPos{std::u32string::npos};
// NOLINTEND(readability-identifier-naming)
////////////////////////////////////////////////////////////
/// \brief Default constructor
///
/// This constructor creates an empty string.
///
////////////////////////////////////////////////////////////
String() = default;
////////////////////////////////////////////////////////////
/// \brief Deleted `std::nullptr_t` constructor
///
/// Disallow construction from `nullptr` literal
///
////////////////////////////////////////////////////////////
String(std::nullptr_t, const std::locale& = {}) = delete;
////////////////////////////////////////////////////////////
/// \brief Construct from a single ANSI character and a locale
///
/// The source character is converted to UTF-32 according
/// to the given locale.
///
/// \param ansiChar ANSI character to convert
/// \param locale Locale to use for conversion
///
////////////////////////////////////////////////////////////
String(char ansiChar, const std::locale& locale = {});
////////////////////////////////////////////////////////////
/// \brief Construct from single wide character
///
/// \param wideChar Wide character to convert
///
////////////////////////////////////////////////////////////
String(wchar_t wideChar);
////////////////////////////////////////////////////////////
/// \brief Construct from single UTF-32 character
///
/// \param utf32Char UTF-32 character to convert
///
////////////////////////////////////////////////////////////
String(char32_t utf32Char);
////////////////////////////////////////////////////////////
/// \brief Construct from a null-terminated C-style ANSI string and a locale
///
/// The source string is converted to UTF-32 according
/// to the given locale.
///
/// \param ansiString ANSI string to convert
/// \param locale Locale to use for conversion
///
////////////////////////////////////////////////////////////
String(const char* ansiString, const std::locale& locale = {});
////////////////////////////////////////////////////////////
/// \brief Construct from an ANSI string and a locale
///
/// The source string is converted to UTF-32 according
/// to the given locale.
///
/// \param ansiString ANSI string to convert
/// \param locale Locale to use for conversion
///
////////////////////////////////////////////////////////////
String(const std::string& ansiString, const std::locale& locale = {});
////////////////////////////////////////////////////////////
/// \brief Construct from null-terminated C-style wide string
///
/// \param wideString Wide string to convert
///
////////////////////////////////////////////////////////////
String(const wchar_t* wideString);
////////////////////////////////////////////////////////////
/// \brief Construct from a wide string
///
/// \param wideString Wide string to convert
///
////////////////////////////////////////////////////////////
String(const std::wstring& wideString);
////////////////////////////////////////////////////////////
/// \brief Construct from a null-terminated C-style UTF-32 string
///
/// \param utf32String UTF-32 string to assign
///
////////////////////////////////////////////////////////////
String(const char32_t* utf32String);
////////////////////////////////////////////////////////////
/// \brief Construct from an UTF-32 string
///
/// \param utf32String UTF-32 string to assign
///
////////////////////////////////////////////////////////////
String(std::u32string utf32String);
////////////////////////////////////////////////////////////
/// \brief Create a new `sf::String` from a UTF-8 encoded string
///
/// \param begin Forward iterator to the beginning of the UTF-8 sequence
/// \param end Forward iterator to the end of the UTF-8 sequence
///
/// \return A `sf::String` containing the source string
///
/// \see `fromUtf16`, `fromUtf32`
///
////////////////////////////////////////////////////////////
template <typename T>
[[nodiscard]] static String fromUtf8(T begin, T end);
////////////////////////////////////////////////////////////
/// \brief Create a new `sf::String` from a UTF-16 encoded string
///
/// \param begin Forward iterator to the beginning of the UTF-16 sequence
/// \param end Forward iterator to the end of the UTF-16 sequence
///
/// \return A `sf::String` containing the source string
///
/// \see `fromUtf8`, `fromUtf32`
///
////////////////////////////////////////////////////////////
template <typename T>
[[nodiscard]] static String fromUtf16(T begin, T end);
////////////////////////////////////////////////////////////
/// \brief Create a new `sf::String` from a UTF-32 encoded string
///
/// This function is provided for consistency, it is equivalent to
/// using the constructors that takes a `const char32_t*` or
/// a `std::u32string`.
///
/// \param begin Forward iterator to the beginning of the UTF-32 sequence
/// \param end Forward iterator to the end of the UTF-32 sequence
///
/// \return A `sf::String` containing the source string
///
/// \see `fromUtf8`, `fromUtf16`
///
////////////////////////////////////////////////////////////
template <typename T>
[[nodiscard]] static String fromUtf32(T begin, T end);
////////////////////////////////////////////////////////////
/// \brief Implicit conversion operator to `std::string` (ANSI string)
///
/// The current global locale is used for conversion. If you
/// want to explicitly specify a locale, see toAnsiString.
/// Characters that do not fit in the target encoding are
/// discarded from the returned string.
/// This operator is defined for convenience, and is equivalent
/// to calling `toAnsiString()`.
///
/// \return Converted ANSI string
///
/// \see `toAnsiString`, `operator std::wstring`
///
////////////////////////////////////////////////////////////
operator std::string() const;
////////////////////////////////////////////////////////////
/// \brief Implicit conversion operator to `std::wstring` (wide string)
///
/// Characters that do not fit in the target encoding are
/// discarded from the returned string.
/// This operator is defined for convenience, and is equivalent
/// to calling `toWideString()`.
///
/// \return Converted wide string
///
/// \see `toWideString`, `operator std::string`
///
////////////////////////////////////////////////////////////
operator std::wstring() const;
////////////////////////////////////////////////////////////
/// \brief Convert the Unicode string to an ANSI string
///
/// The UTF-32 string is converted to an ANSI string in
/// the encoding defined by `locale`.
/// Characters that do not fit in the target encoding are
/// discarded from the returned string.
///
/// \param locale Locale to use for conversion
///
/// \return Converted ANSI string
///
/// \see `toWideString`, `operator std::string`
///
////////////////////////////////////////////////////////////
[[nodiscard]] std::string toAnsiString(const std::locale& locale = {}) const;
////////////////////////////////////////////////////////////
/// \brief Convert the Unicode string to a wide string
///
/// Characters that do not fit in the target encoding are
/// discarded from the returned string.
///
/// \return Converted wide string
///
/// \see `toAnsiString`, `operator std::wstring`
///
////////////////////////////////////////////////////////////
[[nodiscard]] std::wstring toWideString() const;
////////////////////////////////////////////////////////////
/// \brief Convert the Unicode string to a UTF-8 string
///
/// \return Converted UTF-8 string
///
/// \see `toUtf16`, `toUtf32`
///
////////////////////////////////////////////////////////////
[[nodiscard]] sf::U8String toUtf8() const;
////////////////////////////////////////////////////////////
/// \brief Convert the Unicode string to a UTF-16 string
///
/// \return Converted UTF-16 string
///
/// \see `toUtf8`, `toUtf32`
///
////////////////////////////////////////////////////////////
[[nodiscard]] std::u16string toUtf16() const;
////////////////////////////////////////////////////////////
/// \brief Convert the Unicode string to a UTF-32 string
///
/// This function doesn't perform any conversion, since the
/// string is already stored as UTF-32 internally.
///
/// \return Converted UTF-32 string
///
/// \see `toUtf8`, `toUtf16`
///
////////////////////////////////////////////////////////////
[[nodiscard]] std::u32string toUtf32() const;
////////////////////////////////////////////////////////////
/// \brief Overload of `operator+=` to append an UTF-32 string
///
/// \param right String to append
///
/// \return Reference to self
///
////////////////////////////////////////////////////////////
String& operator+=(const String& right);
////////////////////////////////////////////////////////////
/// \brief Overload of `operator[]` to access a character by its position
///
/// This function provides read-only access to characters.
/// Note: the behavior is undefined if `index` is out of range.
///
/// \param index Index of the character to get
///
/// \return Character at position `index`
///
////////////////////////////////////////////////////////////
[[nodiscard]] char32_t operator[](std::size_t index) const;
////////////////////////////////////////////////////////////
/// \brief Overload of `operator[]` to access a character by its position
///
/// This function provides read and write access to characters.
/// Note: the behavior is undefined if `index` is out of range.
///
/// \param index Index of the character to get
///
/// \return Reference to the character at position `index`
///
////////////////////////////////////////////////////////////
[[nodiscard]] char32_t& operator[](std::size_t index);
////////////////////////////////////////////////////////////
/// \brief Clear the string
///
/// This function removes all the characters from the string.
///
/// \see `isEmpty`, `erase`
///
////////////////////////////////////////////////////////////
void clear();
////////////////////////////////////////////////////////////
/// \brief Get the size of the string
///
/// \return Number of characters in the string
///
/// \see `isEmpty`
///
////////////////////////////////////////////////////////////
[[nodiscard]] std::size_t getSize() const;
////////////////////////////////////////////////////////////
/// \brief Check whether the string is empty or not
///
/// \return `true` if the string is empty (i.e. contains no character)
///
/// \see `clear`, `getSize`
///
////////////////////////////////////////////////////////////
[[nodiscard]] bool isEmpty() const;
////////////////////////////////////////////////////////////
/// \brief Erase one or more characters from the string
///
/// This function removes a sequence of `count` characters
/// starting from `position`.
///
/// \param position Position of the first character to erase
/// \param count Number of characters to erase
///
////////////////////////////////////////////////////////////
void erase(std::size_t position, std::size_t count = 1);
////////////////////////////////////////////////////////////
/// \brief Insert one or more characters into the string
///
/// This function inserts the characters of `str`
/// into the string, starting from `position`.
///
/// \param position Position of insertion
/// \param str Characters to insert
///
////////////////////////////////////////////////////////////
void insert(std::size_t position, const String& str);
////////////////////////////////////////////////////////////
/// \brief Find a sequence of one or more characters in the string
///
/// This function searches for the characters of `str`
/// in the string, starting from `start`.
///
/// \param str Characters to find
/// \param start Where to begin searching
///
/// \return Position of `str` in the string, or `String::InvalidPos` if not found
///
////////////////////////////////////////////////////////////
[[nodiscard]] std::size_t find(const String& str, std::size_t start = 0) const;
////////////////////////////////////////////////////////////
/// \brief Replace a substring with another string
///
/// This function replaces the substring that starts at index `position`
/// and spans `length` characters with the string `replaceWith`.
///
/// \param position Index of the first character to be replaced
/// \param length Number of characters to replace. You can pass InvalidPos to
/// replace all characters until the end of the string.
/// \param replaceWith String that replaces the given substring.
///
////////////////////////////////////////////////////////////
void replace(std::size_t position, std::size_t length, const String& replaceWith);
////////////////////////////////////////////////////////////
/// \brief Replace all occurrences of a substring with a replacement string
///
/// This function replaces all occurrences of `searchFor` in this string
/// with the string `replaceWith`.
///
/// \param searchFor The value being searched for
/// \param replaceWith The value that replaces found `searchFor` values
///
////////////////////////////////////////////////////////////
void replace(const String& searchFor, const String& replaceWith);
////////////////////////////////////////////////////////////
/// \brief Return a part of the string
///
/// This function returns the substring that starts at index `position`
/// and spans `length` characters.
///
/// \param position Index of the first character
/// \param length Number of characters to include in the substring (if
/// the string is shorter, as many characters as possible
/// are included). `InvalidPos` can be used to include all
/// characters until the end of the string.
///
/// \return String object containing a substring of this object
///
////////////////////////////////////////////////////////////
[[nodiscard]] String substring(std::size_t position, std::size_t length = InvalidPos) const;
////////////////////////////////////////////////////////////
/// \brief Get a pointer to the C-style array of characters
///
/// This functions provides a read-only access to a
/// null-terminated C-style representation of the string.
/// The returned pointer is temporary and is meant only for
/// immediate use, thus it is not recommended to store it.
///
/// \return Read-only pointer to the array of characters
///
////////////////////////////////////////////////////////////
[[nodiscard]] const char32_t* getData() const;
////////////////////////////////////////////////////////////
/// \brief Return an iterator to the beginning of the string
///
/// \return Read-write iterator to the beginning of the string characters
///
/// \see `end`
///
////////////////////////////////////////////////////////////
[[nodiscard]] Iterator begin();
////////////////////////////////////////////////////////////
/// \brief Return an iterator to the beginning of the string
///
/// \return Read-only iterator to the beginning of the string characters
///
/// \see `end`
///
////////////////////////////////////////////////////////////
[[nodiscard]] ConstIterator begin() const;
////////////////////////////////////////////////////////////
/// \brief Return an iterator to the end of the string
///
/// The end iterator refers to 1 position past the last character;
/// thus it represents an invalid character and should never be
/// accessed.
///
/// \return Read-write iterator to the end of the string characters
///
/// \see `begin`
///
////////////////////////////////////////////////////////////
[[nodiscard]] Iterator end();
////////////////////////////////////////////////////////////
/// \brief Return an iterator to the end of the string
///
/// The end iterator refers to 1 position past the last character;
/// thus it represents an invalid character and should never be
/// accessed.
///
/// \return Read-only iterator to the end of the string characters
///
/// \see `begin`
///
////////////////////////////////////////////////////////////
[[nodiscard]] ConstIterator end() const;
private:
friend SFML_SYSTEM_API bool operator==(const String& left, const String& right);
friend SFML_SYSTEM_API bool operator<(const String& left, const String& right);
////////////////////////////////////////////////////////////
// Member data
////////////////////////////////////////////////////////////
std::u32string m_string; //!< Internal string of UTF-32 characters
};
////////////////////////////////////////////////////////////
/// \relates String
/// \brief Overload of `operator==` to compare two UTF-32 strings
///
/// \param left Left operand (a string)
/// \param right Right operand (a string)
///
/// \return `true` if both strings are equal
///
////////////////////////////////////////////////////////////
[[nodiscard]] SFML_SYSTEM_API bool operator==(const String& left, const String& right);
////////////////////////////////////////////////////////////
/// \relates String
/// \brief Overload of `operator!=` to compare two UTF-32 strings
///
/// \param left Left operand (a string)
/// \param right Right operand (a string)
///
/// \return `true` if both strings are different
///
////////////////////////////////////////////////////////////
[[nodiscard]] SFML_SYSTEM_API bool operator!=(const String& left, const String& right);
////////////////////////////////////////////////////////////
/// \relates String
/// \brief Overload of `operator<` to compare two UTF-32 strings
///
/// \param left Left operand (a string)
/// \param right Right operand (a string)
///
/// \return `true` if `left` is lexicographically before `right`
///
////////////////////////////////////////////////////////////
[[nodiscard]] SFML_SYSTEM_API bool operator<(const String& left, const String& right);
////////////////////////////////////////////////////////////
/// \relates String
/// \brief Overload of `operator>` to compare two UTF-32 strings
///
/// \param left Left operand (a string)
/// \param right Right operand (a string)
///
/// \return `true` if `left` is lexicographically after `right`
///
////////////////////////////////////////////////////////////
[[nodiscard]] SFML_SYSTEM_API bool operator>(const String& left, const String& right);
////////////////////////////////////////////////////////////
/// \relates String
/// \brief Overload of `operator<=` to compare two UTF-32 strings
///
/// \param left Left operand (a string)
/// \param right Right operand (a string)
///
/// \return `true` if `left` is lexicographically before or equivalent to `right`
///
////////////////////////////////////////////////////////////
[[nodiscard]] SFML_SYSTEM_API bool operator<=(const String& left, const String& right);
////////////////////////////////////////////////////////////
/// \relates String
/// \brief Overload of `operator>=` to compare two UTF-32 strings
///
/// \param left Left operand (a string)
/// \param right Right operand (a string)
///
/// \return `true` if `left` is lexicographically after or equivalent to `right`
///
////////////////////////////////////////////////////////////
[[nodiscard]] SFML_SYSTEM_API bool operator>=(const String& left, const String& right);
////////////////////////////////////////////////////////////
/// \relates String
/// \brief Overload of binary `operator+` to concatenate two strings
///
/// \param left Left operand (a string)
/// \param right Right operand (a string)
///
/// \return Concatenated string
///
////////////////////////////////////////////////////////////
[[nodiscard]] SFML_SYSTEM_API String operator+(const String& left, const String& right);
} // namespace sf
#include <SFML/System/String.inl>
////////////////////////////////////////////////////////////
/// \class sf::String
/// \ingroup system
///
/// `sf::String` is a utility string class defined mainly for
/// convenience. It is a Unicode string (implemented using
/// UTF-32), thus it can store any character in the world
/// (European, Chinese, Arabic, Hebrew, etc.).
///
/// It automatically handles conversions from/to ANSI and
/// wide strings, so that you can work with standard string
/// classes and still be compatible with functions taking a
/// `sf::String`.
///
/// \code
/// sf::String s;
///
/// std::string s1 = s; // automatically converted to ANSI string
/// std::wstring s2 = s; // automatically converted to wide string
/// s = "hello"; // automatically converted from ANSI string
/// s = L"hello"; // automatically converted from wide string
/// s += 'a'; // automatically converted from ANSI string
/// s += L'a'; // automatically converted from wide string
/// \endcode
///
/// Conversions involving ANSI strings use the default user locale. However
/// it is possible to use a custom locale if necessary:
/// \code
/// std::locale locale;
/// sf::String s;
/// ...
/// std::string s1 = s.toAnsiString(locale);
/// s = sf::String("hello", locale);
/// \endcode
///
/// `sf::String` defines the most important functions of the
/// standard `std::string` class: removing, random access, iterating,
/// appending, comparing, etc. However it is a simple class
/// provided for convenience, and you may have to consider using
/// a more optimized class if your program requires complex string
/// handling. The automatic conversion functions will then take
/// care of converting your string to `sf::String` whenever SFML
/// requires it.
///
/// Please note that SFML also defines a low-level, generic
/// interface for Unicode handling, see the `sf::Utf` classes.
///
////////////////////////////////////////////////////////////

View File

@ -1,64 +0,0 @@
////////////////////////////////////////////////////////////
//
// SFML - Simple and Fast Multimedia Library
// Copyright (C) 2007-2025 Laurent Gomila (laurent@sfml-dev.org)
//
// This software is provided 'as-is', without any express or implied warranty.
// In no event will the authors be held liable for any damages arising from the use of this software.
//
// Permission is granted to anyone to use this software for any purpose,
// including commercial applications, and to alter it and redistribute it freely,
// subject to the following restrictions:
//
// 1. The origin of this software must not be misrepresented;
// you must not claim that you wrote the original software.
// If you use this software in a product, an acknowledgment
// in the product documentation would be appreciated but is not required.
//
// 2. Altered source versions must be plainly marked as such,
// and must not be misrepresented as being the original software.
//
// 3. This notice may not be removed or altered from any source distribution.
//
////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////
// Headers
////////////////////////////////////////////////////////////
#include <SFML/System/String.hpp> // NOLINT(misc-header-include-cycle)
#include <iterator>
namespace sf
{
////////////////////////////////////////////////////////////
template <typename T>
String String::fromUtf8(T begin, T end)
{
String string;
Utf8::toUtf32(begin, end, std::back_inserter(string.m_string));
return string;
}
////////////////////////////////////////////////////////////
template <typename T>
String String::fromUtf16(T begin, T end)
{
String string;
Utf16::toUtf32(begin, end, std::back_inserter(string.m_string));
return string;
}
////////////////////////////////////////////////////////////
template <typename T>
String String::fromUtf32(T begin, T end)
{
String string;
string.m_string.assign(begin, end);
return string;
}
} // namespace sf

View File

@ -1,76 +0,0 @@
////////////////////////////////////////////////////////////
//
// SFML - Simple and Fast Multimedia Library
// Copyright (C) 2007-2025 Laurent Gomila (laurent@sfml-dev.org)
//
// This software is provided 'as-is', without any express or implied warranty.
// In no event will the authors be held liable for any damages arising from the use of this software.
//
// Permission is granted to anyone to use this software for any purpose,
// including commercial applications, and to alter it and redistribute it freely,
// subject to the following restrictions:
//
// 1. The origin of this software must not be misrepresented;
// you must not claim that you wrote the original software.
// If you use this software in a product, an acknowledgment
// in the product documentation would be appreciated but is not required.
//
// 2. Altered source versions must be plainly marked as such,
// and must not be misrepresented as being the original software.
//
// 3. This notice may not be removed or altered from any source distribution.
//
////////////////////////////////////////////////////////////
#pragma once
////////////////////////////////////////////////////////////
// Headers
////////////////////////////////////////////////////////////
#include <SFML/System/Export.hpp>
#include <chrono>
namespace sf
{
////////////////////////////////////////////////////////////
/// \brief Android, chrono-compatible, suspend-aware clock
///
/// Linux steady clock is represented by `CLOCK_MONOTONIC`.
/// However, this implementation does not work properly for
/// long-running clocks that work in the background when the
/// system is suspended.
///
/// `SuspendAwareClock` uses `CLOCK_BOOTTIME` which is identical
/// to `CLOCK_MONOTONIC`, except that it also includes any time
/// that the system is suspended.
///
/// Note: In most cases, `CLOCK_MONOTONIC` is a better choice.
/// Make sure this implementation is required for your use case.
///
////////////////////////////////////////////////////////////
struct SFML_SYSTEM_API SuspendAwareClock
{
////////////////////////////////////////////////////////////
/// \brief Type traits and static members
///
/// These type traits and static members meet the requirements
/// of a Clock concept in the C++ Standard. More specifically,
/// TrivialClock requirements are met. Thus, naming convention
/// has been kept consistent to allow for extended use e.g.
/// https://en.cppreference.com/w/cpp/chrono/is_clock
///
////////////////////////////////////////////////////////////
using duration = std::chrono::nanoseconds;
using rep = duration::rep;
using period = duration::period;
using time_point = std::chrono::time_point<SuspendAwareClock, duration>;
static constexpr bool is_steady = true; // NOLINT(readability-identifier-naming)
static time_point now() noexcept;
};
} // namespace sf

View File

@ -1,500 +0,0 @@
////////////////////////////////////////////////////////////
//
// SFML - Simple and Fast Multimedia Library
// Copyright (C) 2007-2025 Laurent Gomila (laurent@sfml-dev.org)
//
// This software is provided 'as-is', without any express or implied warranty.
// In no event will the authors be held liable for any damages arising from the use of this software.
//
// Permission is granted to anyone to use this software for any purpose,
// including commercial applications, and to alter it and redistribute it freely,
// subject to the following restrictions:
//
// 1. The origin of this software must not be misrepresented;
// you must not claim that you wrote the original software.
// If you use this software in a product, an acknowledgment
// in the product documentation would be appreciated but is not required.
//
// 2. Altered source versions must be plainly marked as such,
// and must not be misrepresented as being the original software.
//
// 3. This notice may not be removed or altered from any source distribution.
//
////////////////////////////////////////////////////////////
#pragma once
////////////////////////////////////////////////////////////
// Headers
////////////////////////////////////////////////////////////
#include <chrono>
#include <cstdint>
namespace sf
{
////////////////////////////////////////////////////////////
/// \brief Represents a time value
///
////////////////////////////////////////////////////////////
class Time
{
public:
////////////////////////////////////////////////////////////
/// \brief Default constructor
///
/// Sets the time value to zero.
///
////////////////////////////////////////////////////////////
constexpr Time() = default;
////////////////////////////////////////////////////////////
/// \brief Construct from `std::chrono::duration`
///
////////////////////////////////////////////////////////////
template <typename Rep, typename Period>
constexpr Time(const std::chrono::duration<Rep, Period>& duration);
////////////////////////////////////////////////////////////
/// \brief Return the time value as a number of seconds
///
/// \return Time in seconds
///
/// \see `asMilliseconds`, `asMicroseconds`
///
////////////////////////////////////////////////////////////
[[nodiscard]] constexpr float asSeconds() const;
////////////////////////////////////////////////////////////
/// \brief Return the time value as a number of milliseconds
///
/// \return Time in milliseconds
///
/// \see `asSeconds`, `asMicroseconds`
///
////////////////////////////////////////////////////////////
[[nodiscard]] constexpr std::int32_t asMilliseconds() const;
////////////////////////////////////////////////////////////
/// \brief Return the time value as a number of microseconds
///
/// \return Time in microseconds
///
/// \see `asSeconds`, `asMilliseconds`
///
////////////////////////////////////////////////////////////
[[nodiscard]] constexpr std::int64_t asMicroseconds() const;
////////////////////////////////////////////////////////////
/// \brief Return the time value as a `std::chrono::duration`
///
/// \return Time in microseconds
///
////////////////////////////////////////////////////////////
[[nodiscard]] constexpr std::chrono::microseconds toDuration() const;
////////////////////////////////////////////////////////////
/// \brief Implicit conversion to `std::chrono::duration`
///
/// \return Duration in microseconds
///
////////////////////////////////////////////////////////////
template <typename Rep, typename Period>
constexpr operator std::chrono::duration<Rep, Period>() const;
////////////////////////////////////////////////////////////
// Static member data
////////////////////////////////////////////////////////////
// NOLINTNEXTLINE(readability-identifier-naming)
static const Time Zero; //!< Predefined "zero" time value
private:
////////////////////////////////////////////////////////////
// Member data
////////////////////////////////////////////////////////////
std::chrono::microseconds m_microseconds{}; //!< Time value stored as microseconds
};
////////////////////////////////////////////////////////////
/// \relates Time
/// \brief Construct a time value from a number of seconds
///
/// \param amount Number of seconds
///
/// \return Time value constructed from the amount of seconds
///
/// \see `milliseconds`, `microseconds`
///
////////////////////////////////////////////////////////////
[[nodiscard]] constexpr Time seconds(float amount);
////////////////////////////////////////////////////////////
/// \relates Time
/// \brief Construct a time value from a number of milliseconds
///
/// \param amount Number of milliseconds
///
/// \return Time value constructed from the amount of milliseconds
///
/// \see `seconds`, `microseconds`
///
////////////////////////////////////////////////////////////
[[nodiscard]] constexpr Time milliseconds(std::int32_t amount);
////////////////////////////////////////////////////////////
/// \relates Time
/// \brief Construct a time value from a number of microseconds
///
/// \param amount Number of microseconds
///
/// \return Time value constructed from the amount of microseconds
///
/// \see `seconds`, `milliseconds`
///
////////////////////////////////////////////////////////////
[[nodiscard]] constexpr Time microseconds(std::int64_t amount);
////////////////////////////////////////////////////////////
/// \relates Time
/// \brief Overload of `operator==` to compare two time values
///
/// \param left Left operand (a time)
/// \param right Right operand (a time)
///
/// \return `true` if both time values are equal
///
////////////////////////////////////////////////////////////
[[nodiscard]] constexpr bool operator==(Time left, Time right);
////////////////////////////////////////////////////////////
/// \relates Time
/// \brief Overload of `operator!=` to compare two time values
///
/// \param left Left operand (a time)
/// \param right Right operand (a time)
///
/// \return `true` if both time values are different
///
////////////////////////////////////////////////////////////
[[nodiscard]] constexpr bool operator!=(Time left, Time right);
////////////////////////////////////////////////////////////
/// \relates Time
/// \brief Overload of `operator<` to compare two time values
///
/// \param left Left operand (a time)
/// \param right Right operand (a time)
///
/// \return `true` if `left` is lesser than `right`
///
////////////////////////////////////////////////////////////
[[nodiscard]] constexpr bool operator<(Time left, Time right);
////////////////////////////////////////////////////////////
/// \relates Time
/// \brief Overload of `operator>` to compare two time values
///
/// \param left Left operand (a time)
/// \param right Right operand (a time)
///
/// \return `true` if `left` is greater than `right`
///
////////////////////////////////////////////////////////////
[[nodiscard]] constexpr bool operator>(Time left, Time right);
////////////////////////////////////////////////////////////
/// \relates Time
/// \brief Overload of `operator<=` to compare two time values
///
/// \param left Left operand (a time)
/// \param right Right operand (a time)
///
/// \return `true` if `left` is lesser or equal than `right`
///
////////////////////////////////////////////////////////////
[[nodiscard]] constexpr bool operator<=(Time left, Time right);
////////////////////////////////////////////////////////////
/// \relates Time
/// \brief Overload of `operator>=` to compare two time values
///
/// \param left Left operand (a time)
/// \param right Right operand (a time)
///
/// \return `true` if `left` is greater or equal than `right`
///
////////////////////////////////////////////////////////////
[[nodiscard]] constexpr bool operator>=(Time left, Time right);
////////////////////////////////////////////////////////////
/// \relates Time
/// \brief Overload of unary `operator-` to negate a time value
///
/// \param right Right operand (a time)
///
/// \return Opposite of the time value
///
////////////////////////////////////////////////////////////
[[nodiscard]] constexpr Time operator-(Time right);
////////////////////////////////////////////////////////////
/// \relates Time
/// \brief Overload of binary `operator+` to add two time values
///
/// \param left Left operand (a time)
/// \param right Right operand (a time)
///
/// \return Sum of the two times values
///
////////////////////////////////////////////////////////////
[[nodiscard]] constexpr Time operator+(Time left, Time right);
////////////////////////////////////////////////////////////
/// \relates Time
/// \brief Overload of binary `operator+=` to add/assign two time values
///
/// \param left Left operand (a time)
/// \param right Right operand (a time)
///
/// \return Sum of the two times values
///
////////////////////////////////////////////////////////////
constexpr Time& operator+=(Time& left, Time right);
////////////////////////////////////////////////////////////
/// \relates Time
/// \brief Overload of binary `operator-` to subtract two time values
///
/// \param left Left operand (a time)
/// \param right Right operand (a time)
///
/// \return Difference of the two times values
///
////////////////////////////////////////////////////////////
[[nodiscard]] constexpr Time operator-(Time left, Time right);
////////////////////////////////////////////////////////////
/// \relates Time
/// \brief Overload of binary `operator-=` to subtract/assign two time values
///
/// \param left Left operand (a time)
/// \param right Right operand (a time)
///
/// \return Difference of the two times values
///
////////////////////////////////////////////////////////////
constexpr Time& operator-=(Time& left, Time right);
////////////////////////////////////////////////////////////
/// \relates Time
/// \brief Overload of binary `operator*` to scale a time value
///
/// \param left Left operand (a time)
/// \param right Right operand (a number)
///
/// \return `left` multiplied by `right`
///
////////////////////////////////////////////////////////////
[[nodiscard]] constexpr Time operator*(Time left, float right);
////////////////////////////////////////////////////////////
/// \relates Time
/// \brief Overload of binary `operator*` to scale a time value
///
/// \param left Left operand (a time)
/// \param right Right operand (a number)
///
/// \return `left` multiplied by `right`
///
////////////////////////////////////////////////////////////
[[nodiscard]] constexpr Time operator*(Time left, std::int64_t right);
////////////////////////////////////////////////////////////
/// \relates Time
/// \brief Overload of binary `operator*` to scale a time value
///
/// \param left Left operand (a number)
/// \param right Right operand (a time)
///
/// \return `left` multiplied by `right`
///
////////////////////////////////////////////////////////////
[[nodiscard]] constexpr Time operator*(float left, Time right);
////////////////////////////////////////////////////////////
/// \relates Time
/// \brief Overload of binary `operator*` to scale a time value
///
/// \param left Left operand (a number)
/// \param right Right operand (a time)
///
/// \return `left` multiplied by `right`
///
////////////////////////////////////////////////////////////
[[nodiscard]] constexpr Time operator*(std::int64_t left, Time right);
////////////////////////////////////////////////////////////
/// \relates Time
/// \brief Overload of binary `operator*=` to scale/assign a time value
///
/// \param left Left operand (a time)
/// \param right Right operand (a number)
///
/// \return `left` multiplied by `right`
///
////////////////////////////////////////////////////////////
constexpr Time& operator*=(Time& left, float right);
////////////////////////////////////////////////////////////
/// \relates Time
/// \brief Overload of binary `operator*=` to scale/assign a time value
///
/// \param left Left operand (a time)
/// \param right Right operand (a number)
///
/// \return `left` multiplied by `right`
///
////////////////////////////////////////////////////////////
constexpr Time& operator*=(Time& left, std::int64_t right);
////////////////////////////////////////////////////////////
/// \relates Time
/// \brief Overload of binary `operator/` to scale a time value
///
/// \param left Left operand (a time)
/// \param right Right operand (a number)
///
/// \return `left` divided by `right`
///
////////////////////////////////////////////////////////////
[[nodiscard]] constexpr Time operator/(Time left, float right);
////////////////////////////////////////////////////////////
/// \relates Time
/// \brief Overload of binary `operator/` to scale a time value
///
/// \param left Left operand (a time)
/// \param right Right operand (a number)
///
/// \return `left` divided by `right`
///
////////////////////////////////////////////////////////////
[[nodiscard]] constexpr Time operator/(Time left, std::int64_t right);
////////////////////////////////////////////////////////////
/// \relates Time
/// \brief Overload of binary `operator/=` to scale/assign a time value
///
/// \param left Left operand (a time)
/// \param right Right operand (a number)
///
/// \return `left` divided by `right`
///
////////////////////////////////////////////////////////////
constexpr Time& operator/=(Time& left, float right);
////////////////////////////////////////////////////////////
/// \relates Time
/// \brief Overload of binary `operator/=` to scale/assign a time value
///
/// \param left Left operand (a time)
/// \param right Right operand (a number)
///
/// \return `left` divided by `right`
///
////////////////////////////////////////////////////////////
constexpr Time& operator/=(Time& left, std::int64_t right);
////////////////////////////////////////////////////////////
/// \relates Time
/// \brief Overload of binary `operator/` to compute the ratio of two time values
///
/// \param left Left operand (a time)
/// \param right Right operand (a time)
///
/// \return `left` divided by `right`
///
////////////////////////////////////////////////////////////
[[nodiscard]] constexpr float operator/(Time left, Time right);
////////////////////////////////////////////////////////////
/// \relates Time
/// \brief Overload of binary `operator%` to compute remainder of a time value
///
/// \param left Left operand (a time)
/// \param right Right operand (a time)
///
/// \return `left` modulo `right`
///
////////////////////////////////////////////////////////////
[[nodiscard]] constexpr Time operator%(Time left, Time right);
////////////////////////////////////////////////////////////
/// \relates Time
/// \brief Overload of binary `operator%=` to compute/assign remainder of a time value
///
/// \param left Left operand (a time)
/// \param right Right operand (a time)
///
/// \return `left` modulo `right`
///
////////////////////////////////////////////////////////////
constexpr Time& operator%=(Time& left, Time right);
} // namespace sf
#include <SFML/System/Time.inl>
////////////////////////////////////////////////////////////
/// \class sf::Time
/// \ingroup system
///
/// `sf::Time` encapsulates a time value in a flexible way.
/// It allows to define a time value either as a number of
/// seconds, milliseconds or microseconds. It also works the
/// other way round: you can read a time value as either
/// a number of seconds, milliseconds or microseconds. It
/// even interoperates with the `<chrono>` header. You can
/// construct an `sf::Time` from a `chrono::duration` and read
/// any `sf::Time` as a chrono::duration.
///
/// By using such a flexible interface, the API doesn't
/// impose any fixed type or resolution for time values,
/// and let the user choose its own favorite representation.
///
/// Time values support the usual mathematical operations:
/// you can add or subtract two times, multiply or divide
/// a time by a number, compare two times, etc.
///
/// Since they represent a time span and not an absolute time
/// value, times can also be negative.
///
/// Usage example:
/// \code
/// sf::Time t1 = sf::seconds(0.1f);
/// std::int32_t milli = t1.asMilliseconds(); // 100
///
/// sf::Time t2 = sf::milliseconds(30);
/// std::int64_t micro = t2.asMicroseconds(); // 30000
///
/// sf::Time t3 = sf::microseconds(-800000);
/// float sec = t3.asSeconds(); // -0.8
///
/// sf::Time t4 = std::chrono::milliseconds(250);
/// std::chrono::microseconds micro2 = t4.toDuration(); // 250000us
/// \endcode
///
/// \code
/// void update(sf::Time elapsed)
/// {
/// position += speed * elapsed.asSeconds();
/// }
///
/// update(sf::milliseconds(100));
/// \endcode
///
/// \see `sf::Clock`
///
////////////////////////////////////////////////////////////

View File

@ -1,284 +0,0 @@
////////////////////////////////////////////////////////////
//
// SFML - Simple and Fast Multimedia Library
// Copyright (C) 2007-2025 Laurent Gomila (laurent@sfml-dev.org)
//
// This software is provided 'as-is', without any express or implied warranty.
// In no event will the authors be held liable for any damages arising from the use of this software.
//
// Permission is granted to anyone to use this software for any purpose,
// including commercial applications, and to alter it and redistribute it freely,
// subject to the following restrictions:
//
// 1. The origin of this software must not be misrepresented;
// you must not claim that you wrote the original software.
// If you use this software in a product, an acknowledgment
// in the product documentation would be appreciated but is not required.
//
// 2. Altered source versions must be plainly marked as such,
// and must not be misrepresented as being the original software.
//
// 3. This notice may not be removed or altered from any source distribution.
//
////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////
// Headers
////////////////////////////////////////////////////////////
#include <SFML/System/Time.hpp> // NOLINT(misc-header-include-cycle)
#include <ratio>
#include <cassert>
namespace sf
{
////////////////////////////////////////////////////////////
template <typename Rep, typename Period>
constexpr Time::Time(const std::chrono::duration<Rep, Period>& duration) : m_microseconds(duration)
{
}
////////////////////////////////////////////////////////////
constexpr float Time::asSeconds() const
{
return std::chrono::duration<float>(m_microseconds).count();
}
////////////////////////////////////////////////////////////
constexpr std::int32_t Time::asMilliseconds() const
{
return std::chrono::duration_cast<std::chrono::duration<std::int32_t, std::milli>>(m_microseconds).count();
}
////////////////////////////////////////////////////////////
constexpr std::int64_t Time::asMicroseconds() const
{
return m_microseconds.count();
}
////////////////////////////////////////////////////////////
constexpr std::chrono::microseconds Time::toDuration() const
{
return m_microseconds;
}
////////////////////////////////////////////////////////////
template <typename Rep, typename Period>
constexpr Time::operator std::chrono::duration<Rep, Period>() const
{
return m_microseconds;
}
////////////////////////////////////////////////////////////
constexpr Time seconds(float amount)
{
return std::chrono::duration_cast<std::chrono::microseconds>(std::chrono::duration<float>(amount));
}
////////////////////////////////////////////////////////////
constexpr Time milliseconds(std::int32_t amount)
{
return std::chrono::milliseconds(amount);
}
////////////////////////////////////////////////////////////
constexpr Time microseconds(std::int64_t amount)
{
return std::chrono::microseconds(amount);
}
////////////////////////////////////////////////////////////
constexpr bool operator==(Time left, Time right)
{
return left.asMicroseconds() == right.asMicroseconds();
}
////////////////////////////////////////////////////////////
constexpr bool operator!=(Time left, Time right)
{
return left.asMicroseconds() != right.asMicroseconds();
}
////////////////////////////////////////////////////////////
constexpr bool operator<(Time left, Time right)
{
return left.asMicroseconds() < right.asMicroseconds();
}
////////////////////////////////////////////////////////////
constexpr bool operator>(Time left, Time right)
{
return left.asMicroseconds() > right.asMicroseconds();
}
////////////////////////////////////////////////////////////
constexpr bool operator<=(Time left, Time right)
{
return left.asMicroseconds() <= right.asMicroseconds();
}
////////////////////////////////////////////////////////////
constexpr bool operator>=(Time left, Time right)
{
return left.asMicroseconds() >= right.asMicroseconds();
}
////////////////////////////////////////////////////////////
constexpr Time operator-(Time right)
{
return microseconds(-right.asMicroseconds());
}
////////////////////////////////////////////////////////////
constexpr Time operator+(Time left, Time right)
{
return microseconds(left.asMicroseconds() + right.asMicroseconds());
}
////////////////////////////////////////////////////////////
constexpr Time& operator+=(Time& left, Time right)
{
return left = left + right;
}
////////////////////////////////////////////////////////////
constexpr Time operator-(Time left, Time right)
{
return microseconds(left.asMicroseconds() - right.asMicroseconds());
}
////////////////////////////////////////////////////////////
constexpr Time& operator-=(Time& left, Time right)
{
return left = left - right;
}
////////////////////////////////////////////////////////////
constexpr Time operator*(Time left, float right)
{
return seconds(left.asSeconds() * right);
}
////////////////////////////////////////////////////////////
constexpr Time operator*(Time left, std::int64_t right)
{
return microseconds(left.asMicroseconds() * right);
}
////////////////////////////////////////////////////////////
constexpr Time operator*(float left, Time right)
{
return right * left;
}
////////////////////////////////////////////////////////////
constexpr Time operator*(std::int64_t left, Time right)
{
return right * left;
}
////////////////////////////////////////////////////////////
constexpr Time& operator*=(Time& left, float right)
{
return left = left * right;
}
////////////////////////////////////////////////////////////
constexpr Time& operator*=(Time& left, std::int64_t right)
{
return left = left * right;
}
////////////////////////////////////////////////////////////
constexpr Time operator/(Time left, float right)
{
assert(right != 0 && "Time::operator/ cannot divide by 0");
return seconds(left.asSeconds() / right);
}
////////////////////////////////////////////////////////////
constexpr Time operator/(Time left, std::int64_t right)
{
assert(right != 0 && "Time::operator/ cannot divide by 0");
return microseconds(left.asMicroseconds() / right);
}
////////////////////////////////////////////////////////////
constexpr Time& operator/=(Time& left, float right)
{
assert(right != 0 && "Time::operator/= cannot divide by 0");
return left = left / right;
}
////////////////////////////////////////////////////////////
constexpr Time& operator/=(Time& left, std::int64_t right)
{
assert(right != 0 && "Time::operator/= cannot divide by 0");
return left = left / right;
}
////////////////////////////////////////////////////////////
constexpr float operator/(Time left, Time right)
{
assert(right.asMicroseconds() != 0 && "Time::operator/ cannot divide by 0");
return left.asSeconds() / right.asSeconds();
}
////////////////////////////////////////////////////////////
constexpr Time operator%(Time left, Time right)
{
assert(right.asMicroseconds() != 0 && "Time::operator% cannot modulus by 0");
return microseconds(left.asMicroseconds() % right.asMicroseconds());
}
////////////////////////////////////////////////////////////
constexpr Time& operator%=(Time& left, Time right)
{
assert(right.asMicroseconds() != 0 && "Time::operator%= cannot modulus by 0");
return left = left % right;
}
////////////////////////////////////////////////////////////
// Static member data
////////////////////////////////////////////////////////////
// Note: the 'inline' keyword here is technically not required, but VS2019 fails
// to compile with a bogus "multiple definition" error if not explicitly used.
inline constexpr Time Time::Zero;
} // namespace sf

View File

@ -1,764 +0,0 @@
////////////////////////////////////////////////////////////
//
// SFML - Simple and Fast Multimedia Library
// Copyright (C) 2007-2025 Laurent Gomila (laurent@sfml-dev.org)
//
// This software is provided 'as-is', without any express or implied warranty.
// In no event will the authors be held liable for any damages arising from the use of this software.
//
// Permission is granted to anyone to use this software for any purpose,
// including commercial applications, and to alter it and redistribute it freely,
// subject to the following restrictions:
//
// 1. The origin of this software must not be misrepresented;
// you must not claim that you wrote the original software.
// If you use this software in a product, an acknowledgment
// in the product documentation would be appreciated but is not required.
//
// 2. Altered source versions must be plainly marked as such,
// and must not be misrepresented as being the original software.
//
// 3. This notice may not be removed or altered from any source distribution.
//
////////////////////////////////////////////////////////////
#pragma once
////////////////////////////////////////////////////////////
// Headers
////////////////////////////////////////////////////////////
#include <SFML/Config.hpp>
#include <array>
#include <locale>
#include <cstdint>
#include <cstdlib>
namespace sf
{
namespace priv
{
template <class InputIt, class OutputIt>
OutputIt copy(InputIt first, InputIt last, OutputIt dFirst);
}
template <unsigned int N>
class Utf;
////////////////////////////////////////////////////////////
/// \brief Specialization of the Utf template for UTF-8
///
////////////////////////////////////////////////////////////
template <>
class Utf<8>
{
public:
////////////////////////////////////////////////////////////
/// \brief Decode a single UTF-8 character
///
/// Decoding a character means finding its unique 32-bits
/// code (called the codepoint) in the Unicode standard.
///
/// \param begin Iterator pointing to the beginning of the input sequence
/// \param end Iterator pointing to the end of the input sequence
/// \param output Codepoint of the decoded UTF-8 character
/// \param replacement Replacement character to use in case the UTF-8 sequence is invalid
///
/// \return Iterator pointing to one past the last read element of the input sequence
///
////////////////////////////////////////////////////////////
template <typename In>
static In decode(In begin, In end, char32_t& output, char32_t replacement = 0);
////////////////////////////////////////////////////////////
/// \brief Encode a single UTF-8 character
///
/// Encoding a character means converting a unique 32-bits
/// code (called the codepoint) in the target encoding, UTF-8.
///
/// \param input Codepoint to encode as UTF-8
/// \param output Iterator pointing to the beginning of the output sequence
/// \param replacement Replacement for characters not convertible to UTF-8 (use 0 to skip them)
///
/// \return Iterator to the end of the output sequence which has been written
///
////////////////////////////////////////////////////////////
template <typename Out>
static Out encode(char32_t input, Out output, std::uint8_t replacement = 0);
////////////////////////////////////////////////////////////
/// \brief Advance to the next UTF-8 character
///
/// This function is necessary for multi-elements encodings, as
/// a single character may use more than 1 storage element.
///
/// \param begin Iterator pointing to the beginning of the input sequence
/// \param end Iterator pointing to the end of the input sequence
///
/// \return Iterator pointing to one past the last read element of the input sequence
///
////////////////////////////////////////////////////////////
template <typename In>
static In next(In begin, In end);
////////////////////////////////////////////////////////////
/// \brief Count the number of characters of a UTF-8 sequence
///
/// This function is necessary for multi-elements encodings, as
/// a single character may use more than 1 storage element, thus the
/// total size can be different from (begin - end).
///
/// \param begin Iterator pointing to the beginning of the input sequence
/// \param end Iterator pointing to the end of the input sequence
///
/// \return Iterator pointing to one past the last read element of the input sequence
///
////////////////////////////////////////////////////////////
template <typename In>
static std::size_t count(In begin, In end);
////////////////////////////////////////////////////////////
/// \brief Convert an ANSI characters range to UTF-8
///
/// The current global locale will be used by default, unless you
/// pass a custom one in the `locale` parameter.
///
/// \param begin Iterator pointing to the beginning of the input sequence
/// \param end Iterator pointing to the end of the input sequence
/// \param output Iterator pointing to the beginning of the output sequence
/// \param locale Locale to use for conversion
///
/// \return Iterator to the end of the output sequence which has been written
///
////////////////////////////////////////////////////////////
template <typename In, typename Out>
static Out fromAnsi(In begin, In end, Out output, const std::locale& locale = {});
////////////////////////////////////////////////////////////
/// \brief Convert a wide characters range to UTF-8
///
/// \param begin Iterator pointing to the beginning of the input sequence
/// \param end Iterator pointing to the end of the input sequence
/// \param output Iterator pointing to the beginning of the output sequence
///
/// \return Iterator to the end of the output sequence which has been written
///
////////////////////////////////////////////////////////////
template <typename In, typename Out>
static Out fromWide(In begin, In end, Out output);
////////////////////////////////////////////////////////////
/// \brief Convert a latin-1 (ISO-5589-1) characters range to UTF-8
///
/// \param begin Iterator pointing to the beginning of the input sequence
/// \param end Iterator pointing to the end of the input sequence
/// \param output Iterator pointing to the beginning of the output sequence
///
/// \return Iterator to the end of the output sequence which has been written
///
////////////////////////////////////////////////////////////
template <typename In, typename Out>
static Out fromLatin1(In begin, In end, Out output);
////////////////////////////////////////////////////////////
/// \brief Convert an UTF-8 characters range to ANSI characters
///
/// The current global locale will be used by default, unless you
/// pass a custom one in the `locale` parameter.
///
/// \param begin Iterator pointing to the beginning of the input sequence
/// \param end Iterator pointing to the end of the input sequence
/// \param output Iterator pointing to the beginning of the output sequence
/// \param replacement Replacement for characters not convertible to ANSI (use 0 to skip them)
/// \param locale Locale to use for conversion
///
/// \return Iterator to the end of the output sequence which has been written
///
////////////////////////////////////////////////////////////
template <typename In, typename Out>
static Out toAnsi(In begin, In end, Out output, char replacement = 0, const std::locale& locale = {});
////////////////////////////////////////////////////////////
/// \brief Convert an UTF-8 characters range to wide characters
///
/// \param begin Iterator pointing to the beginning of the input sequence
/// \param end Iterator pointing to the end of the input sequence
/// \param output Iterator pointing to the beginning of the output sequence
/// \param replacement Replacement for characters not convertible to wide (use 0 to skip them)
///
/// \return Iterator to the end of the output sequence which has been written
///
////////////////////////////////////////////////////////////
template <typename In, typename Out>
static Out toWide(In begin, In end, Out output, wchar_t replacement = 0);
////////////////////////////////////////////////////////////
/// \brief Convert an UTF-8 characters range to latin-1 (ISO-5589-1) characters
///
/// \param begin Iterator pointing to the beginning of the input sequence
/// \param end Iterator pointing to the end of the input sequence
/// \param output Iterator pointing to the beginning of the output sequence
/// \param replacement Replacement for characters not convertible to wide (use 0 to skip them)
///
/// \return Iterator to the end of the output sequence which has been written
///
////////////////////////////////////////////////////////////
template <typename In, typename Out>
static Out toLatin1(In begin, In end, Out output, char replacement = 0);
////////////////////////////////////////////////////////////
/// \brief Convert a UTF-8 characters range to UTF-8
///
/// This functions does nothing more than a direct copy;
/// it is defined only to provide the same interface as other
/// specializations of the `sf::Utf<>` template, and allow
/// generic code to be written on top of it.
///
/// \param begin Iterator pointing to the beginning of the input sequence
/// \param end Iterator pointing to the end of the input sequence
/// \param output Iterator pointing to the beginning of the output sequence
///
/// \return Iterator to the end of the output sequence which has been written
///
////////////////////////////////////////////////////////////
template <typename In, typename Out>
static Out toUtf8(In begin, In end, Out output);
////////////////////////////////////////////////////////////
/// \brief Convert a UTF-8 characters range to UTF-16
///
/// \param begin Iterator pointing to the beginning of the input sequence
/// \param end Iterator pointing to the end of the input sequence
/// \param output Iterator pointing to the beginning of the output sequence
///
/// \return Iterator to the end of the output sequence which has been written
///
////////////////////////////////////////////////////////////
template <typename In, typename Out>
static Out toUtf16(In begin, In end, Out output);
////////////////////////////////////////////////////////////
/// \brief Convert a UTF-8 characters range to UTF-32
///
/// \param begin Iterator pointing to the beginning of the input sequence
/// \param end Iterator pointing to the end of the input sequence
/// \param output Iterator pointing to the beginning of the output sequence
///
/// \return Iterator to the end of the output sequence which has been written
///
////////////////////////////////////////////////////////////
template <typename In, typename Out>
static Out toUtf32(In begin, In end, Out output);
};
////////////////////////////////////////////////////////////
/// \brief Specialization of the Utf template for UTF-16
///
////////////////////////////////////////////////////////////
template <>
class Utf<16>
{
public:
////////////////////////////////////////////////////////////
/// \brief Decode a single UTF-16 character
///
/// Decoding a character means finding its unique 32-bits
/// code (called the codepoint) in the Unicode standard.
///
/// \param begin Iterator pointing to the beginning of the input sequence
/// \param end Iterator pointing to the end of the input sequence
/// \param output Codepoint of the decoded UTF-16 character
/// \param replacement Replacement character to use in case the UTF-8 sequence is invalid
///
/// \return Iterator pointing to one past the last read element of the input sequence
///
////////////////////////////////////////////////////////////
template <typename In>
static In decode(In begin, In end, char32_t& output, char32_t replacement = 0);
////////////////////////////////////////////////////////////
/// \brief Encode a single UTF-16 character
///
/// Encoding a character means converting a unique 32-bits
/// code (called the codepoint) in the target encoding, UTF-16.
///
/// \param input Codepoint to encode as UTF-16
/// \param output Iterator pointing to the beginning of the output sequence
/// \param replacement Replacement for characters not convertible to UTF-16 (use 0 to skip them)
///
/// \return Iterator to the end of the output sequence which has been written
///
////////////////////////////////////////////////////////////
template <typename Out>
static Out encode(char32_t input, Out output, char16_t replacement = 0);
////////////////////////////////////////////////////////////
/// \brief Advance to the next UTF-16 character
///
/// This function is necessary for multi-elements encodings, as
/// a single character may use more than 1 storage element.
///
/// \param begin Iterator pointing to the beginning of the input sequence
/// \param end Iterator pointing to the end of the input sequence
///
/// \return Iterator pointing to one past the last read element of the input sequence
///
////////////////////////////////////////////////////////////
template <typename In>
static In next(In begin, In end);
////////////////////////////////////////////////////////////
/// \brief Count the number of characters of a UTF-16 sequence
///
/// This function is necessary for multi-elements encodings, as
/// a single character may use more than 1 storage element, thus the
/// total size can be different from (begin - end).
///
/// \param begin Iterator pointing to the beginning of the input sequence
/// \param end Iterator pointing to the end of the input sequence
///
/// \return Iterator pointing to one past the last read element of the input sequence
///
////////////////////////////////////////////////////////////
template <typename In>
static std::size_t count(In begin, In end);
////////////////////////////////////////////////////////////
/// \brief Convert an ANSI characters range to UTF-16
///
/// The current global locale will be used by default, unless you
/// pass a custom one in the `locale` parameter.
///
/// \param begin Iterator pointing to the beginning of the input sequence
/// \param end Iterator pointing to the end of the input sequence
/// \param output Iterator pointing to the beginning of the output sequence
/// \param locale Locale to use for conversion
///
/// \return Iterator to the end of the output sequence which has been written
///
////////////////////////////////////////////////////////////
template <typename In, typename Out>
static Out fromAnsi(In begin, In end, Out output, const std::locale& locale = {});
////////////////////////////////////////////////////////////
/// \brief Convert a wide characters range to UTF-16
///
/// \param begin Iterator pointing to the beginning of the input sequence
/// \param end Iterator pointing to the end of the input sequence
/// \param output Iterator pointing to the beginning of the output sequence
///
/// \return Iterator to the end of the output sequence which has been written
///
////////////////////////////////////////////////////////////
template <typename In, typename Out>
static Out fromWide(In begin, In end, Out output);
////////////////////////////////////////////////////////////
/// \brief Convert a latin-1 (ISO-5589-1) characters range to UTF-16
///
/// \param begin Iterator pointing to the beginning of the input sequence
/// \param end Iterator pointing to the end of the input sequence
/// \param output Iterator pointing to the beginning of the output sequence
///
/// \return Iterator to the end of the output sequence which has been written
///
////////////////////////////////////////////////////////////
template <typename In, typename Out>
static Out fromLatin1(In begin, In end, Out output);
////////////////////////////////////////////////////////////
/// \brief Convert an UTF-16 characters range to ANSI characters
///
/// The current global locale will be used by default, unless you
/// pass a custom one in the `locale` parameter.
///
/// \param begin Iterator pointing to the beginning of the input sequence
/// \param end Iterator pointing to the end of the input sequence
/// \param output Iterator pointing to the beginning of the output sequence
/// \param replacement Replacement for characters not convertible to ANSI (use 0 to skip them)
/// \param locale Locale to use for conversion
///
/// \return Iterator to the end of the output sequence which has been written
///
////////////////////////////////////////////////////////////
template <typename In, typename Out>
static Out toAnsi(In begin, In end, Out output, char replacement = 0, const std::locale& locale = {});
////////////////////////////////////////////////////////////
/// \brief Convert an UTF-16 characters range to wide characters
///
/// \param begin Iterator pointing to the beginning of the input sequence
/// \param end Iterator pointing to the end of the input sequence
/// \param output Iterator pointing to the beginning of the output sequence
/// \param replacement Replacement for characters not convertible to wide (use 0 to skip them)
///
/// \return Iterator to the end of the output sequence which has been written
///
////////////////////////////////////////////////////////////
template <typename In, typename Out>
static Out toWide(In begin, In end, Out output, wchar_t replacement = 0);
////////////////////////////////////////////////////////////
/// \brief Convert an UTF-16 characters range to latin-1 (ISO-5589-1) characters
///
/// \param begin Iterator pointing to the beginning of the input sequence
/// \param end Iterator pointing to the end of the input sequence
/// \param output Iterator pointing to the beginning of the output sequence
/// \param replacement Replacement for characters not convertible to wide (use 0 to skip them)
///
/// \return Iterator to the end of the output sequence which has been written
///
////////////////////////////////////////////////////////////
template <typename In, typename Out>
static Out toLatin1(In begin, In end, Out output, char replacement = 0);
////////////////////////////////////////////////////////////
/// \brief Convert a UTF-16 characters range to UTF-8
///
/// \param begin Iterator pointing to the beginning of the input sequence
/// \param end Iterator pointing to the end of the input sequence
/// \param output Iterator pointing to the beginning of the output sequence
///
/// \return Iterator to the end of the output sequence which has been written
///
////////////////////////////////////////////////////////////
template <typename In, typename Out>
static Out toUtf8(In begin, In end, Out output);
////////////////////////////////////////////////////////////
/// \brief Convert a UTF-16 characters range to UTF-16
///
/// This functions does nothing more than a direct copy;
/// it is defined only to provide the same interface as other
/// specializations of the `sf::Utf<>` template, and allow
/// generic code to be written on top of it.
///
/// \param begin Iterator pointing to the beginning of the input sequence
/// \param end Iterator pointing to the end of the input sequence
/// \param output Iterator pointing to the beginning of the output sequence
///
/// \return Iterator to the end of the output sequence which has been written
///
////////////////////////////////////////////////////////////
template <typename In, typename Out>
static Out toUtf16(In begin, In end, Out output);
////////////////////////////////////////////////////////////
/// \brief Convert a UTF-16 characters range to UTF-32
///
/// \param begin Iterator pointing to the beginning of the input sequence
/// \param end Iterator pointing to the end of the input sequence
/// \param output Iterator pointing to the beginning of the output sequence
///
/// \return Iterator to the end of the output sequence which has been written
///
////////////////////////////////////////////////////////////
template <typename In, typename Out>
static Out toUtf32(In begin, In end, Out output);
};
////////////////////////////////////////////////////////////
/// \brief Specialization of the Utf template for UTF-32
///
////////////////////////////////////////////////////////////
template <>
class Utf<32>
{
public:
////////////////////////////////////////////////////////////
/// \brief Decode a single UTF-32 character
///
/// Decoding a character means finding its unique 32-bits
/// code (called the codepoint) in the Unicode standard.
/// For UTF-32, the character value is the same as the codepoint.
///
/// \param begin Iterator pointing to the beginning of the input sequence
/// \param end Iterator pointing to the end of the input sequence
/// \param output Codepoint of the decoded UTF-32 character
/// \param replacement Replacement character to use in case the UTF-8 sequence is invalid
///
/// \return Iterator pointing to one past the last read element of the input sequence
///
////////////////////////////////////////////////////////////
template <typename In>
static In decode(In begin, In end, char32_t& output, char32_t replacement = 0);
////////////////////////////////////////////////////////////
/// \brief Encode a single UTF-32 character
///
/// Encoding a character means converting a unique 32-bits
/// code (called the codepoint) in the target encoding, UTF-32.
/// For UTF-32, the codepoint is the same as the character value.
///
/// \param input Codepoint to encode as UTF-32
/// \param output Iterator pointing to the beginning of the output sequence
/// \param replacement Replacement for characters not convertible to UTF-32 (use 0 to skip them)
///
/// \return Iterator to the end of the output sequence which has been written
///
////////////////////////////////////////////////////////////
template <typename Out>
static Out encode(char32_t input, Out output, char32_t replacement = 0);
////////////////////////////////////////////////////////////
/// \brief Advance to the next UTF-32 character
///
/// This function is trivial for UTF-32, which can store
/// every character in a single storage element.
///
/// \param begin Iterator pointing to the beginning of the input sequence
/// \param end Iterator pointing to the end of the input sequence
///
/// \return Iterator pointing to one past the last read element of the input sequence
///
////////////////////////////////////////////////////////////
template <typename In>
static In next(In begin, In end);
////////////////////////////////////////////////////////////
/// \brief Count the number of characters of a UTF-32 sequence
///
/// This function is trivial for UTF-32, which can store
/// every character in a single storage element.
///
/// \param begin Iterator pointing to the beginning of the input sequence
/// \param end Iterator pointing to the end of the input sequence
///
/// \return Iterator pointing to one past the last read element of the input sequence
///
////////////////////////////////////////////////////////////
template <typename In>
static std::size_t count(In begin, In end);
////////////////////////////////////////////////////////////
/// \brief Convert an ANSI characters range to UTF-32
///
/// The current global locale will be used by default, unless you
/// pass a custom one in the `locale` parameter.
///
/// \param begin Iterator pointing to the beginning of the input sequence
/// \param end Iterator pointing to the end of the input sequence
/// \param output Iterator pointing to the beginning of the output sequence
/// \param locale Locale to use for conversion
///
/// \return Iterator to the end of the output sequence which has been written
///
////////////////////////////////////////////////////////////
template <typename In, typename Out>
static Out fromAnsi(In begin, In end, Out output, const std::locale& locale = {});
////////////////////////////////////////////////////////////
/// \brief Convert a wide characters range to UTF-32
///
/// \param begin Iterator pointing to the beginning of the input sequence
/// \param end Iterator pointing to the end of the input sequence
/// \param output Iterator pointing to the beginning of the output sequence
///
/// \return Iterator to the end of the output sequence which has been written
///
////////////////////////////////////////////////////////////
template <typename In, typename Out>
static Out fromWide(In begin, In end, Out output);
////////////////////////////////////////////////////////////
/// \brief Convert a latin-1 (ISO-5589-1) characters range to UTF-32
///
/// \param begin Iterator pointing to the beginning of the input sequence
/// \param end Iterator pointing to the end of the input sequence
/// \param output Iterator pointing to the beginning of the output sequence
///
/// \return Iterator to the end of the output sequence which has been written
///
////////////////////////////////////////////////////////////
template <typename In, typename Out>
static Out fromLatin1(In begin, In end, Out output);
////////////////////////////////////////////////////////////
/// \brief Convert an UTF-32 characters range to ANSI characters
///
/// The current global locale will be used by default, unless you
/// pass a custom one in the `locale` parameter.
///
/// \param begin Iterator pointing to the beginning of the input sequence
/// \param end Iterator pointing to the end of the input sequence
/// \param output Iterator pointing to the beginning of the output sequence
/// \param replacement Replacement for characters not convertible to ANSI (use 0 to skip them)
/// \param locale Locale to use for conversion
///
/// \return Iterator to the end of the output sequence which has been written
///
////////////////////////////////////////////////////////////
template <typename In, typename Out>
static Out toAnsi(In begin, In end, Out output, char replacement = 0, const std::locale& locale = {});
////////////////////////////////////////////////////////////
/// \brief Convert an UTF-32 characters range to wide characters
///
/// \param begin Iterator pointing to the beginning of the input sequence
/// \param end Iterator pointing to the end of the input sequence
/// \param output Iterator pointing to the beginning of the output sequence
/// \param replacement Replacement for characters not convertible to wide (use 0 to skip them)
///
/// \return Iterator to the end of the output sequence which has been written
///
////////////////////////////////////////////////////////////
template <typename In, typename Out>
static Out toWide(In begin, In end, Out output, wchar_t replacement = 0);
////////////////////////////////////////////////////////////
/// \brief Convert an UTF-16 characters range to latin-1 (ISO-5589-1) characters
///
/// \param begin Iterator pointing to the beginning of the input sequence
/// \param end Iterator pointing to the end of the input sequence
/// \param output Iterator pointing to the beginning of the output sequence
/// \param replacement Replacement for characters not convertible to wide (use 0 to skip them)
///
/// \return Iterator to the end of the output sequence which has been written
///
////////////////////////////////////////////////////////////
template <typename In, typename Out>
static Out toLatin1(In begin, In end, Out output, char replacement = 0);
////////////////////////////////////////////////////////////
/// \brief Convert a UTF-32 characters range to UTF-8
///
/// \param begin Iterator pointing to the beginning of the input sequence
/// \param end Iterator pointing to the end of the input sequence
/// \param output Iterator pointing to the beginning of the output sequence
///
/// \return Iterator to the end of the output sequence which has been written
///
////////////////////////////////////////////////////////////
template <typename In, typename Out>
static Out toUtf8(In begin, In end, Out output);
////////////////////////////////////////////////////////////
/// \brief Convert a UTF-32 characters range to UTF-16
///
/// \param begin Iterator pointing to the beginning of the input sequence
/// \param end Iterator pointing to the end of the input sequence
/// \param output Iterator pointing to the beginning of the output sequence
///
/// \return Iterator to the end of the output sequence which has been written
///
////////////////////////////////////////////////////////////
template <typename In, typename Out>
static Out toUtf16(In begin, In end, Out output);
////////////////////////////////////////////////////////////
/// \brief Convert a UTF-32 characters range to UTF-32
///
/// This functions does nothing more than a direct copy;
/// it is defined only to provide the same interface as other
/// specializations of the `sf::Utf<>` template, and allow
/// generic code to be written on top of it.
///
/// \param begin Iterator pointing to the beginning of the input sequence
/// \param end Iterator pointing to the end of the input sequence
/// \param output Iterator pointing to the beginning of the output sequence
///
/// \return Iterator to the end of the output sequence which has been written
///
////////////////////////////////////////////////////////////
template <typename In, typename Out>
static Out toUtf32(In begin, In end, Out output);
////////////////////////////////////////////////////////////
/// \brief Decode a single ANSI character to UTF-32
///
/// This function does not exist in other specializations
/// of `sf::Utf<>`, it is defined for convenience (it is used by
/// several other conversion functions).
///
/// \param input Input ANSI character
/// \param locale Locale to use for conversion
///
/// \return Converted character
///
////////////////////////////////////////////////////////////
template <typename In>
static char32_t decodeAnsi(In input, const std::locale& locale = {});
////////////////////////////////////////////////////////////
/// \brief Decode a single wide character to UTF-32
///
/// This function does not exist in other specializations
/// of `sf::Utf<>`, it is defined for convenience (it is used by
/// several other conversion functions).
///
/// \param input Input wide character
///
/// \return Converted character
///
////////////////////////////////////////////////////////////
template <typename In>
static char32_t decodeWide(In input);
////////////////////////////////////////////////////////////
/// \brief Encode a single UTF-32 character to ANSI
///
/// This function does not exist in other specializations
/// of `sf::Utf<>`, it is defined for convenience (it is used by
/// several other conversion functions).
///
/// \param codepoint Iterator pointing to the beginning of the input sequence
/// \param output Iterator pointing to the beginning of the output sequence
/// \param replacement Replacement if the input character is not convertible to ANSI (use 0 to skip it)
/// \param locale Locale to use for conversion
///
/// \return Iterator to the end of the output sequence which has been written
///
////////////////////////////////////////////////////////////
template <typename Out>
static Out encodeAnsi(char32_t codepoint, Out output, char replacement = 0, const std::locale& locale = {});
////////////////////////////////////////////////////////////
/// \brief Encode a single UTF-32 character to wide
///
/// This function does not exist in other specializations
/// of `sf::Utf<>`, it is defined for convenience (it is used by
/// several other conversion functions).
///
/// \param codepoint Iterator pointing to the beginning of the input sequence
/// \param output Iterator pointing to the beginning of the output sequence
/// \param replacement Replacement if the input character is not convertible to wide (use 0 to skip it)
///
/// \return Iterator to the end of the output sequence which has been written
///
////////////////////////////////////////////////////////////
template <typename Out>
static Out encodeWide(char32_t codepoint, Out output, wchar_t replacement = 0);
};
// Make type aliases to get rid of the template syntax
using Utf8 = Utf<8>;
using Utf16 = Utf<16>;
using Utf32 = Utf<32>;
} // namespace sf
#include <SFML/System/Utf.inl>
////////////////////////////////////////////////////////////
/// \class sf::Utf
/// \ingroup system
///
/// Utility class providing generic functions for UTF conversions.
///
/// `sf::Utf` is a low-level, generic interface for counting, iterating,
/// encoding and decoding Unicode characters and strings. It is able
/// to handle ANSI, wide, latin-1, UTF-8, UTF-16 and UTF-32 encodings.
///
/// `sf::Utf<X>` functions are all static, these classes are not meant to
/// be instantiated. All the functions are template, so that you
/// can use any character / string type for a given encoding.
///
/// It has 3 specializations:
/// \li `sf::Utf<8>` (with `sf::Utf8` type alias)
/// \li `sf::Utf<16>` (with `sf::Utf16` type alias)
/// \li `sf::Utf<32>` (with `sf::Utf32` type alias)
///
////////////////////////////////////////////////////////////

View File

@ -1,732 +0,0 @@
////////////////////////////////////////////////////////////
//
// SFML - Simple and Fast Multimedia Library
// Copyright (C) 2007-2025 Laurent Gomila (laurent@sfml-dev.org)
//
// This software is provided 'as-is', without any express or implied warranty.
// In no event will the authors be held liable for any damages arising from the use of this software.
//
// Permission is granted to anyone to use this software for any purpose,
// including commercial applications, and to alter it and redistribute it freely,
// subject to the following restrictions:
//
// 1. The origin of this software must not be misrepresented;
// you must not claim that you wrote the original software.
// If you use this software in a product, an acknowledgment
// in the product documentation would be appreciated but is not required.
//
// 2. Altered source versions must be plainly marked as such,
// and must not be misrepresented as being the original software.
//
// 3. This notice may not be removed or altered from any source distribution.
//
////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////
// Headers
////////////////////////////////////////////////////////////
#include <SFML/System/Utf.hpp> // NOLINT(misc-header-include-cycle)
////////////////////////////////////////////////////////////
// References:
//
// https://www.unicode.org/
// https://www.unicode.org/Public/PROGRAMS/CVTUTF/ConvertUTF.c
// https://www.unicode.org/Public/PROGRAMS/CVTUTF/ConvertUTF.h
// https://people.w3.org/rishida/scripts/uniview/conversion
//
////////////////////////////////////////////////////////////
namespace sf
{
////////////////////////////////////////////////////////////
template <typename InputIt, typename OutputIt>
OutputIt priv::copy(InputIt first, InputIt last, OutputIt dFirst)
{
while (first != last)
*dFirst++ = static_cast<typename OutputIt::container_type::value_type>(*first++);
return dFirst;
}
template <typename In>
In Utf<8>::decode(In begin, In end, char32_t& output, char32_t replacement)
{
// clang-format off
// Some useful precomputed data
static constexpr std::array<std::uint8_t, 256> trailing =
{
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 3, 3, 3, 3, 3, 3, 3, 3, 4, 4, 4, 4, 5, 5, 5, 5
};
static constexpr std::array<std::uint32_t, 6> offsets =
{
0x00000000, 0x00003080, 0x000E2080, 0x03C82080, 0xFA082080, 0x82082080
};
// clang-format on
// decode the character
const auto trailingBytes = trailing[static_cast<std::uint8_t>(*begin)];
if (trailingBytes < std::distance(begin, end))
{
output = 0;
// clang-format off
switch (trailingBytes)
{
case 5: output += static_cast<std::uint8_t>(*begin++); output <<= 6; [[fallthrough]];
case 4: output += static_cast<std::uint8_t>(*begin++); output <<= 6; [[fallthrough]];
case 3: output += static_cast<std::uint8_t>(*begin++); output <<= 6; [[fallthrough]];
case 2: output += static_cast<std::uint8_t>(*begin++); output <<= 6; [[fallthrough]];
case 1: output += static_cast<std::uint8_t>(*begin++); output <<= 6; [[fallthrough]];
case 0: output += static_cast<std::uint8_t>(*begin++);
}
// clang-format on
output -= offsets[trailingBytes];
}
else
{
// Incomplete character
begin = end;
output = replacement;
}
return begin;
}
////////////////////////////////////////////////////////////
template <typename Out>
Out Utf<8>::encode(char32_t input, Out output, std::uint8_t replacement)
{
// Some useful precomputed data
static constexpr std::array<std::uint8_t, 7> firstBytes = {0x00, 0x00, 0xC0, 0xE0, 0xF0, 0xF8, 0xFC};
// encode the character
if ((input > 0x0010FFFF) || ((input >= 0xD800) && (input <= 0xDBFF)))
{
// Invalid character
if (replacement)
*output++ = static_cast<typename Out::container_type::value_type>(replacement);
}
else
{
// Valid character
// Get the number of bytes to write
std::size_t bytestoWrite = 1;
// clang-format off
if (input < 0x80) bytestoWrite = 1;
else if (input < 0x800) bytestoWrite = 2;
else if (input < 0x10000) bytestoWrite = 3;
else if (input <= 0x0010FFFF) bytestoWrite = 4;
// clang-format on
// Extract the bytes to write
std::array<std::byte, 4> bytes{};
// clang-format off
switch (bytestoWrite)
{
case 4: bytes[3] = static_cast<std::byte>((input | 0x80) & 0xBF); input >>= 6; [[fallthrough]];
case 3: bytes[2] = static_cast<std::byte>((input | 0x80) & 0xBF); input >>= 6; [[fallthrough]];
case 2: bytes[1] = static_cast<std::byte>((input | 0x80) & 0xBF); input >>= 6; [[fallthrough]];
case 1: bytes[0] = static_cast<std::byte> (input | firstBytes[bytestoWrite]);
}
// clang-format on
// Add them to the output
output = priv::copy(bytes.data(), bytes.data() + bytestoWrite, output);
}
return output;
}
////////////////////////////////////////////////////////////
template <typename In>
In Utf<8>::next(In begin, In end)
{
char32_t codepoint = 0;
return decode(begin, end, codepoint);
}
////////////////////////////////////////////////////////////
template <typename In>
std::size_t Utf<8>::count(In begin, In end)
{
std::size_t length = 0;
while (begin != end)
{
begin = next(begin, end);
++length;
}
return length;
}
////////////////////////////////////////////////////////////
template <typename In, typename Out>
Out Utf<8>::fromAnsi(In begin, In end, Out output, const std::locale& locale)
{
while (begin != end)
{
const char32_t codepoint = Utf<32>::decodeAnsi(*begin++, locale);
output = encode(codepoint, output);
}
return output;
}
////////////////////////////////////////////////////////////
template <typename In, typename Out>
Out Utf<8>::fromWide(In begin, In end, Out output)
{
while (begin != end)
{
char32_t codepoint = Utf<32>::decodeWide(*begin++);
output = encode(codepoint, output);
}
return output;
}
////////////////////////////////////////////////////////////
template <typename In, typename Out>
Out Utf<8>::fromLatin1(In begin, In end, Out output)
{
// Latin-1 is directly compatible with Unicode encodings,
// and can thus be treated as (a sub-range of) UTF-32
while (begin != end)
output = encode(*begin++, output);
return output;
}
////////////////////////////////////////////////////////////
template <typename In, typename Out>
Out Utf<8>::toAnsi(In begin, In end, Out output, char replacement, const std::locale& locale)
{
while (begin != end)
{
char32_t codepoint = 0;
begin = decode(begin, end, codepoint);
output = Utf<32>::encodeAnsi(codepoint, output, replacement, locale);
}
return output;
}
////////////////////////////////////////////////////////////
template <typename In, typename Out>
Out Utf<8>::toWide(In begin, In end, Out output, wchar_t replacement)
{
while (begin != end)
{
char32_t codepoint = 0;
begin = decode(begin, end, codepoint);
output = Utf<32>::encodeWide(codepoint, output, replacement);
}
return output;
}
////////////////////////////////////////////////////////////
template <typename In, typename Out>
Out Utf<8>::toLatin1(In begin, In end, Out output, char replacement)
{
// Latin-1 is directly compatible with Unicode encodings,
// and can thus be treated as (a sub-range of) UTF-32
while (begin != end)
{
char32_t codepoint = 0;
begin = decode(begin, end, codepoint);
*output++ = codepoint < 256 ? static_cast<char>(codepoint) : replacement;
}
return output;
}
////////////////////////////////////////////////////////////
template <typename In, typename Out>
Out Utf<8>::toUtf8(In begin, In end, Out output)
{
return priv::copy(begin, end, output);
}
////////////////////////////////////////////////////////////
template <typename In, typename Out>
Out Utf<8>::toUtf16(In begin, In end, Out output)
{
while (begin != end)
{
char32_t codepoint = 0;
begin = decode(begin, end, codepoint);
output = Utf<16>::encode(codepoint, output);
}
return output;
}
////////////////////////////////////////////////////////////
template <typename In, typename Out>
Out Utf<8>::toUtf32(In begin, In end, Out output)
{
while (begin != end)
{
char32_t codepoint = 0;
begin = decode(begin, end, codepoint);
*output++ = codepoint;
}
return output;
}
////////////////////////////////////////////////////////////
template <typename In>
In Utf<16>::decode(In begin, In end, char32_t& output, char32_t replacement)
{
const char16_t first = *begin++;
// If it's a surrogate pair, first convert to a single UTF-32 character
if ((first >= 0xD800) && (first <= 0xDBFF))
{
if (begin != end)
{
const std::uint32_t second = *begin++;
if ((second >= 0xDC00) && (second <= 0xDFFF))
{
// The second element is valid: convert the two elements to a UTF-32 character
output = ((first - 0xD800u) << 10) + (second - 0xDC00) + 0x0010000;
}
else
{
// Invalid character
output = replacement;
}
}
else
{
// Invalid character
begin = end;
output = replacement;
}
}
else
{
// We can make a direct copy
output = static_cast<char32_t>(first);
}
return begin;
}
////////////////////////////////////////////////////////////
template <typename Out>
Out Utf<16>::encode(char32_t input, Out output, char16_t replacement)
{
if (input <= 0xFFFF)
{
// The character can be copied directly, we just need to check if it's in the valid range
if ((input >= 0xD800) && (input <= 0xDFFF))
{
// Invalid character (this range is reserved)
if (replacement)
*output++ = replacement;
}
else
{
// Valid character directly convertible to a single UTF-16 character
*output++ = static_cast<char16_t>(input);
}
}
else if (input > 0x0010FFFF)
{
// Invalid character (greater than the maximum Unicode value)
if (replacement)
*output++ = replacement;
}
else
{
// The input character will be converted to two UTF-16 elements
input -= 0x0010000;
*output++ = static_cast<char16_t>((input >> 10) + 0xD800);
*output++ = static_cast<char16_t>((input & 0x3FFUL) + 0xDC00);
}
return output;
}
////////////////////////////////////////////////////////////
template <typename In>
In Utf<16>::next(In begin, In end)
{
char32_t codepoint = 0;
return decode(begin, end, codepoint);
}
////////////////////////////////////////////////////////////
template <typename In>
std::size_t Utf<16>::count(In begin, In end)
{
std::size_t length = 0;
while (begin != end)
{
begin = next(begin, end);
++length;
}
return length;
}
////////////////////////////////////////////////////////////
template <typename In, typename Out>
Out Utf<16>::fromAnsi(In begin, In end, Out output, const std::locale& locale)
{
while (begin != end)
{
char32_t codepoint = Utf<32>::decodeAnsi(*begin++, locale);
output = encode(codepoint, output);
}
return output;
}
////////////////////////////////////////////////////////////
template <typename In, typename Out>
Out Utf<16>::fromWide(In begin, In end, Out output)
{
while (begin != end)
{
char32_t codepoint = Utf<32>::decodeWide(*begin++);
output = encode(codepoint, output);
}
return output;
}
////////////////////////////////////////////////////////////
template <typename In, typename Out>
Out Utf<16>::fromLatin1(In begin, In end, Out output)
{
// Latin-1 is directly compatible with Unicode encodings,
// and can thus be treated as (a sub-range of) UTF-32
return priv::copy(begin, end, output);
}
////////////////////////////////////////////////////////////
template <typename In, typename Out>
Out Utf<16>::toAnsi(In begin, In end, Out output, char replacement, const std::locale& locale)
{
while (begin != end)
{
char32_t codepoint = 0;
begin = decode(begin, end, codepoint);
output = Utf<32>::encodeAnsi(codepoint, output, replacement, locale);
}
return output;
}
////////////////////////////////////////////////////////////
template <typename In, typename Out>
Out Utf<16>::toWide(In begin, In end, Out output, wchar_t replacement)
{
while (begin != end)
{
char32_t codepoint = 0;
begin = decode(begin, end, codepoint);
output = Utf<32>::encodeWide(codepoint, output, replacement);
}
return output;
}
////////////////////////////////////////////////////////////
template <typename In, typename Out>
Out Utf<16>::toLatin1(In begin, In end, Out output, char replacement)
{
// Latin-1 is directly compatible with Unicode encodings,
// and can thus be treated as (a sub-range of) UTF-32
while (begin != end)
{
*output++ = *begin < 256 ? static_cast<char>(*begin) : replacement;
++begin;
}
return output;
}
////////////////////////////////////////////////////////////
template <typename In, typename Out>
Out Utf<16>::toUtf8(In begin, In end, Out output)
{
while (begin != end)
{
char32_t codepoint = 0;
begin = decode(begin, end, codepoint);
output = Utf<8>::encode(codepoint, output);
}
return output;
}
////////////////////////////////////////////////////////////
template <typename In, typename Out>
Out Utf<16>::toUtf16(In begin, In end, Out output)
{
return priv::copy(begin, end, output);
}
////////////////////////////////////////////////////////////
template <typename In, typename Out>
Out Utf<16>::toUtf32(In begin, In end, Out output)
{
while (begin != end)
{
char32_t codepoint = 0;
begin = decode(begin, end, codepoint);
*output++ = codepoint;
}
return output;
}
////////////////////////////////////////////////////////////
template <typename In>
In Utf<32>::decode(In begin, In /*end*/, char32_t& output, char32_t /*replacement*/)
{
output = *begin++;
return begin;
}
////////////////////////////////////////////////////////////
template <typename Out>
Out Utf<32>::encode(char32_t input, Out output, char32_t /*replacement*/)
{
*output++ = input;
return output;
}
////////////////////////////////////////////////////////////
template <typename In>
In Utf<32>::next(In begin, In /*end*/)
{
return ++begin;
}
////////////////////////////////////////////////////////////
template <typename In>
std::size_t Utf<32>::count(In begin, In end)
{
return static_cast<std::size_t>(end - begin);
}
////////////////////////////////////////////////////////////
template <typename In, typename Out>
Out Utf<32>::fromAnsi(In begin, In end, Out output, const std::locale& locale)
{
while (begin != end)
*output++ = decodeAnsi(*begin++, locale);
return output;
}
////////////////////////////////////////////////////////////
template <typename In, typename Out>
Out Utf<32>::fromWide(In begin, In end, Out output)
{
while (begin != end)
*output++ = decodeWide(*begin++);
return output;
}
////////////////////////////////////////////////////////////
template <typename In, typename Out>
Out Utf<32>::fromLatin1(In begin, In end, Out output)
{
// Latin-1 is directly compatible with Unicode encodings,
// and can thus be treated as (a sub-range of) UTF-32
return priv::copy(begin, end, output);
}
////////////////////////////////////////////////////////////
template <typename In, typename Out>
Out Utf<32>::toAnsi(In begin, In end, Out output, char replacement, const std::locale& locale)
{
while (begin != end)
output = encodeAnsi(*begin++, output, replacement, locale);
return output;
}
////////////////////////////////////////////////////////////
template <typename In, typename Out>
Out Utf<32>::toWide(In begin, In end, Out output, wchar_t replacement)
{
while (begin != end)
output = encodeWide(*begin++, output, replacement);
return output;
}
////////////////////////////////////////////////////////////
template <typename In, typename Out>
Out Utf<32>::toLatin1(In begin, In end, Out output, char replacement)
{
// Latin-1 is directly compatible with Unicode encodings,
// and can thus be treated as (a sub-range of) UTF-32
while (begin != end)
{
*output++ = *begin < 256 ? static_cast<char>(*begin) : replacement;
++begin;
}
return output;
}
////////////////////////////////////////////////////////////
template <typename In, typename Out>
Out Utf<32>::toUtf8(In begin, In end, Out output)
{
while (begin != end)
output = Utf<8>::encode(*begin++, output);
return output;
}
////////////////////////////////////////////////////////////
template <typename In, typename Out>
Out Utf<32>::toUtf16(In begin, In end, Out output)
{
while (begin != end)
output = Utf<16>::encode(*begin++, output);
return output;
}
////////////////////////////////////////////////////////////
template <typename In, typename Out>
Out Utf<32>::toUtf32(In begin, In end, Out output)
{
return priv::copy(begin, end, output);
}
////////////////////////////////////////////////////////////
template <typename In>
char32_t Utf<32>::decodeAnsi(In input, const std::locale& locale)
{
// Get the facet of the locale which deals with character conversion
const auto& facet = std::use_facet<std::ctype<wchar_t>>(locale);
// Use the facet to convert each character of the input string
return static_cast<char32_t>(facet.widen(input));
}
////////////////////////////////////////////////////////////
template <typename In>
char32_t Utf<32>::decodeWide(In input)
{
// The encoding of wide characters is not well defined and is left to the system;
// however we can safely assume that it is UCS-2 on Windows and
// UCS-4 on Unix systems.
// In both cases, a simple copy is enough (UCS-2 is a subset of UCS-4,
// and UCS-4 *is* UTF-32).
return static_cast<char32_t>(input);
}
////////////////////////////////////////////////////////////
template <typename Out>
Out Utf<32>::encodeAnsi(char32_t codepoint, Out output, char replacement, const std::locale& locale)
{
// Get the facet of the locale which deals with character conversion
const auto& facet = std::use_facet<std::ctype<wchar_t>>(locale);
// Use the facet to convert each character of the input string
*output++ = facet.narrow(static_cast<wchar_t>(codepoint), replacement);
return output;
}
////////////////////////////////////////////////////////////
template <typename Out>
Out Utf<32>::encodeWide(char32_t codepoint, Out output, wchar_t replacement)
{
// The encoding of wide characters is not well defined and is left to the system;
// however we can safely assume that it is UCS-2 on Windows and
// UCS-4 on Unix systems.
// For UCS-2 we need to check if the source characters fits in (UCS-2 is a subset of UCS-4).
// For UCS-4 we can do a direct copy (UCS-4 *is* UTF-32).
if constexpr (sizeof(wchar_t) == 4)
{
*output++ = static_cast<wchar_t>(codepoint);
}
else
{
if ((codepoint <= 0xFFFF) && ((codepoint < 0xD800) || (codepoint > 0xDFFF)))
{
*output++ = static_cast<wchar_t>(codepoint);
}
else if (replacement)
{
*output++ = replacement;
}
}
return output;
}
} // namespace sf

View File

@ -1,435 +0,0 @@
////////////////////////////////////////////////////////////
//
// SFML - Simple and Fast Multimedia Library
// Copyright (C) 2007-2025 Laurent Gomila (laurent@sfml-dev.org)
//
// This software is provided 'as-is', without any express or implied warranty.
// In no event will the authors be held liable for any damages arising from the use of this software.
//
// Permission is granted to anyone to use this software for any purpose,
// including commercial applications, and to alter it and redistribute it freely,
// subject to the following restrictions:
//
// 1. The origin of this software must not be misrepresented;
// you must not claim that you wrote the original software.
// If you use this software in a product, an acknowledgment
// in the product documentation would be appreciated but is not required.
//
// 2. Altered source versions must be plainly marked as such,
// and must not be misrepresented as being the original software.
//
// 3. This notice may not be removed or altered from any source distribution.
//
////////////////////////////////////////////////////////////
#pragma once
#include <SFML/System/Export.hpp>
#include <SFML/System/Angle.hpp>
namespace sf
{
////////////////////////////////////////////////////////////
/// \brief Class template for manipulating
/// 2-dimensional vectors
///
////////////////////////////////////////////////////////////
template <typename T>
class Vector2
{
public:
////////////////////////////////////////////////////////////
/// \brief Default constructor
///
/// Creates a `Vector2(0, 0)`.
///
////////////////////////////////////////////////////////////
constexpr Vector2() = default;
////////////////////////////////////////////////////////////
/// \brief Construct the vector from cartesian coordinates
///
/// \param x X coordinate
/// \param y Y coordinate
///
////////////////////////////////////////////////////////////
constexpr Vector2(T x, T y);
////////////////////////////////////////////////////////////
/// \brief Converts the vector to another type of vector
///
////////////////////////////////////////////////////////////
template <typename U>
constexpr explicit operator Vector2<U>() const;
////////////////////////////////////////////////////////////
/// \brief Construct the vector from polar coordinates <i><b>(floating-point)</b></i>
///
/// \param r Length of vector (can be negative)
/// \param phi Angle from X axis
///
/// Note that this constructor is lossy: calling `length()` and `angle()`
/// may return values different to those provided in this constructor.
///
/// In particular, these transforms can be applied:
/// * `Vector2(r, phi) == Vector2(-r, phi + 180_deg)`
/// * `Vector2(r, phi) == Vector2(r, phi + n * 360_deg)`
///
////////////////////////////////////////////////////////////
SFML_SYSTEM_API Vector2(T r, Angle phi);
////////////////////////////////////////////////////////////
/// \brief Length of the vector <i><b>(floating-point)</b></i>.
///
/// If you are not interested in the actual length, but only in comparisons, consider using `lengthSquared()`.
///
////////////////////////////////////////////////////////////
[[nodiscard]] SFML_SYSTEM_API T length() const;
////////////////////////////////////////////////////////////
/// \brief Square of vector's length.
///
/// Suitable for comparisons, more efficient than `length()`.
///
////////////////////////////////////////////////////////////
[[nodiscard]] constexpr T lengthSquared() const;
////////////////////////////////////////////////////////////
/// \brief Vector with same direction but length 1 <i><b>(floating-point)</b></i>.
///
/// \pre `*this` is no zero vector.
///
////////////////////////////////////////////////////////////
[[nodiscard]] SFML_SYSTEM_API Vector2 normalized() const;
////////////////////////////////////////////////////////////
/// \brief Signed angle from `*this` to `rhs` <i><b>(floating-point)</b></i>.
///
/// \return The smallest angle which rotates `*this` in positive
/// or negative direction, until it has the same direction as `rhs`.
/// The result has a sign and lies in the range [-180, 180) degrees.
/// \pre Neither `*this` nor `rhs` is a zero vector.
///
////////////////////////////////////////////////////////////
[[nodiscard]] SFML_SYSTEM_API Angle angleTo(Vector2 rhs) const;
////////////////////////////////////////////////////////////
/// \brief Signed angle from +X or (1,0) vector <i><b>(floating-point)</b></i>.
///
/// For example, the vector (1,0) corresponds to 0 degrees, (0,1) corresponds to 90 degrees.
///
/// \return Angle in the range [-180, 180) degrees.
/// \pre This vector is no zero vector.
///
////////////////////////////////////////////////////////////
[[nodiscard]] SFML_SYSTEM_API Angle angle() const;
////////////////////////////////////////////////////////////
/// \brief Rotate by angle \c phi <i><b>(floating-point)</b></i>.
///
/// Returns a vector with same length but different direction.
///
/// In SFML's default coordinate system with +X right and +Y down,
/// this amounts to a clockwise rotation by `phi`.
///
////////////////////////////////////////////////////////////
[[nodiscard]] SFML_SYSTEM_API Vector2 rotatedBy(Angle phi) const;
////////////////////////////////////////////////////////////
/// \brief Projection of this vector onto `axis` <i><b>(floating-point)</b></i>.
///
/// \param axis Vector being projected onto. Need not be normalized.
/// \pre `axis` must not have length zero.
///
////////////////////////////////////////////////////////////
[[nodiscard]] SFML_SYSTEM_API Vector2 projectedOnto(Vector2 axis) const;
////////////////////////////////////////////////////////////
/// \brief Returns a perpendicular vector.
///
/// Returns `*this` rotated by +90 degrees; (x,y) becomes (-y,x).
/// For example, the vector (1,0) is transformed to (0,1).
///
/// In SFML's default coordinate system with +X right and +Y down,
/// this amounts to a clockwise rotation.
///
////////////////////////////////////////////////////////////
[[nodiscard]] constexpr Vector2 perpendicular() const;
////////////////////////////////////////////////////////////
/// \brief Dot product of two 2D vectors.
///
////////////////////////////////////////////////////////////
[[nodiscard]] constexpr T dot(Vector2 rhs) const;
////////////////////////////////////////////////////////////
/// \brief Z component of the cross product of two 2D vectors.
///
/// Treats the operands as 3D vectors, computes their cross product
/// and returns the result's Z component (X and Y components are always zero).
///
////////////////////////////////////////////////////////////
[[nodiscard]] constexpr T cross(Vector2 rhs) const;
////////////////////////////////////////////////////////////
/// \brief Component-wise multiplication of `*this` and `rhs`.
///
/// Computes `(lhs.x*rhs.x, lhs.y*rhs.y)`.
///
/// Scaling is the most common use case for component-wise multiplication/division.
/// This operation is also known as the Hadamard or Schur product.
///
////////////////////////////////////////////////////////////
[[nodiscard]] constexpr Vector2 componentWiseMul(Vector2 rhs) const;
////////////////////////////////////////////////////////////
/// \brief Component-wise division of `*this` and `rhs`.
///
/// Computes `(lhs.x/rhs.x, lhs.y/rhs.y)`.
///
/// Scaling is the most common use case for component-wise multiplication/division.
///
/// \pre Neither component of `rhs` is zero.
///
////////////////////////////////////////////////////////////
[[nodiscard]] constexpr Vector2 componentWiseDiv(Vector2 rhs) const;
////////////////////////////////////////////////////////////
// Member data
////////////////////////////////////////////////////////////
T x{}; //!< X coordinate of the vector
T y{}; //!< Y coordinate of the vector
};
// Define the most common types
using Vector2i = Vector2<int>;
using Vector2u = Vector2<unsigned int>;
using Vector2f = Vector2<float>;
////////////////////////////////////////////////////////////
/// \relates Vector2
/// \brief Overload of unary `operator-`
///
/// \param right Vector to negate
///
/// \return Member-wise opposite of the vector
///
////////////////////////////////////////////////////////////
template <typename T>
[[nodiscard]] constexpr Vector2<T> operator-(Vector2<T> right);
////////////////////////////////////////////////////////////
/// \relates Vector2
/// \brief Overload of binary `operator+=`
///
/// This operator performs a member-wise addition of both vectors,
/// and assigns the result to `left`.
///
/// \param left Left operand (a vector)
/// \param right Right operand (a vector)
///
/// \return Reference to `left`
///
////////////////////////////////////////////////////////////
template <typename T>
constexpr Vector2<T>& operator+=(Vector2<T>& left, Vector2<T> right);
////////////////////////////////////////////////////////////
/// \relates Vector2
/// \brief Overload of binary `operator-=`
///
/// This operator performs a member-wise subtraction of both vectors,
/// and assigns the result to `left`.
///
/// \param left Left operand (a vector)
/// \param right Right operand (a vector)
///
/// \return Reference to \c left
///
////////////////////////////////////////////////////////////
template <typename T>
constexpr Vector2<T>& operator-=(Vector2<T>& left, Vector2<T> right);
////////////////////////////////////////////////////////////
/// \relates Vector2
/// \brief Overload of binary `operator+`
///
/// \param left Left operand (a vector)
/// \param right Right operand (a vector)
///
/// \return Member-wise addition of both vectors
///
////////////////////////////////////////////////////////////
template <typename T>
[[nodiscard]] constexpr Vector2<T> operator+(Vector2<T> left, Vector2<T> right);
////////////////////////////////////////////////////////////
/// \relates Vector2
/// \brief Overload of binary `operator-`
///
/// \param left Left operand (a vector)
/// \param right Right operand (a vector)
///
/// \return Member-wise subtraction of both vectors
///
////////////////////////////////////////////////////////////
template <typename T>
[[nodiscard]] constexpr Vector2<T> operator-(Vector2<T> left, Vector2<T> right);
////////////////////////////////////////////////////////////
/// \relates Vector2
/// \brief Overload of binary `operator*`
///
/// \param left Left operand (a vector)
/// \param right Right operand (a scalar value)
///
/// \return Member-wise multiplication by `right`
///
////////////////////////////////////////////////////////////
template <typename T>
[[nodiscard]] constexpr Vector2<T> operator*(Vector2<T> left, T right);
////////////////////////////////////////////////////////////
/// \relates Vector2
/// \brief Overload of binary `operator*`
///
/// \param left Left operand (a scalar value)
/// \param right Right operand (a vector)
///
/// \return Member-wise multiplication by `left`
///
////////////////////////////////////////////////////////////
template <typename T>
[[nodiscard]] constexpr Vector2<T> operator*(T left, Vector2<T> right);
////////////////////////////////////////////////////////////
/// \relates Vector2
/// \brief Overload of binary `operator*=`
///
/// This operator performs a member-wise multiplication by `right`,
/// and assigns the result to `left`.
///
/// \param left Left operand (a vector)
/// \param right Right operand (a scalar value)
///
/// \return Reference to `left`
///
////////////////////////////////////////////////////////////
template <typename T>
constexpr Vector2<T>& operator*=(Vector2<T>& left, T right);
////////////////////////////////////////////////////////////
/// \relates Vector2
/// \brief Overload of binary `operator/`
///
/// \param left Left operand (a vector)
/// \param right Right operand (a scalar value)
///
/// \return Member-wise division by `right`
///
////////////////////////////////////////////////////////////
template <typename T>
[[nodiscard]] constexpr Vector2<T> operator/(Vector2<T> left, T right);
////////////////////////////////////////////////////////////
/// \relates Vector2
/// \brief Overload of binary `operator/=`
///
/// This operator performs a member-wise division by `right`,
/// and assigns the result to `left`.
///
/// \param left Left operand (a vector)
/// \param right Right operand (a scalar value)
///
/// \return Reference to `left`
///
////////////////////////////////////////////////////////////
template <typename T>
constexpr Vector2<T>& operator/=(Vector2<T>& left, T right);
////////////////////////////////////////////////////////////
/// \relates Vector2
/// \brief Overload of binary `operator==`
///
/// This operator compares strict equality between two vectors.
///
/// \param left Left operand (a vector)
/// \param right Right operand (a vector)
///
/// \return `true` if `left` is equal to `right`
///
////////////////////////////////////////////////////////////
template <typename T>
[[nodiscard]] constexpr bool operator==(Vector2<T> left, Vector2<T> right);
////////////////////////////////////////////////////////////
/// \relates Vector2
/// \brief Overload of binary `operator!=`
///
/// This operator compares strict difference between two vectors.
///
/// \param left Left operand (a vector)
/// \param right Right operand (a vector)
///
/// \return `true` if `left` is not equal to `right`
///
////////////////////////////////////////////////////////////
template <typename T>
[[nodiscard]] constexpr bool operator!=(Vector2<T> left, Vector2<T> right);
} // namespace sf
#include <SFML/System/Vector2.inl>
////////////////////////////////////////////////////////////
/// \class sf::Vector2
/// \ingroup system
///
/// `sf::Vector2` is a simple class that defines a mathematical
/// vector with two coordinates (x and y). It can be used to
/// represent anything that has two dimensions: a size, a point,
/// a velocity, a scale, etc.
///
/// The API provides basic arithmetic (addition, subtraction, scale), as
/// well as more advanced geometric operations, such as dot/cross products,
/// length and angle computations, projections, rotations, etc.
///
/// The template parameter T is the type of the coordinates. It
/// can be any type that supports arithmetic operations (+, -, /, *)
/// and comparisons (==, !=), for example int or float.
/// Note that some operations are only meaningful for vectors where T is
/// a floating point type (e.g. float or double), often because
/// results cannot be represented accurately with integers.
/// The method documentation mentions "(floating-point)" in those cases.
///
/// You generally don't have to care about the templated form (`sf::Vector2<T>`),
/// the most common specializations have special type aliases:
/// \li `sf::Vector2<float>` is `sf::Vector2f`
/// \li `sf::Vector2<int>` is `sf::Vector2i`
/// \li `sf::Vector2<unsigned int>` is `sf::Vector2u`
///
/// The `sf::Vector2` class has a simple interface, its x and y members
/// can be accessed directly (there are no accessors like setX(), getX()).
///
/// Usage example:
/// \code
/// sf::Vector2f v(16.5f, 24.f);
/// v.x = 18.2f;
/// float y = v.y;
///
/// sf::Vector2f w = v * 5.f;
/// sf::Vector2f u;
/// u = v + w;
///
/// float s = v.dot(w);
///
/// bool different = (v != u);
/// \endcode
///
/// Note: for 3-dimensional vectors, see `sf::Vector3`.
///
////////////////////////////////////////////////////////////

View File

@ -1,217 +0,0 @@
////////////////////////////////////////////////////////////
//
// SFML - Simple and Fast Multimedia Library
// Copyright (C) 2007-2025 Laurent Gomila (laurent@sfml-dev.org)
//
// This software is provided 'as-is', without any express or implied warranty.
// In no event will the authors be held liable for any damages arising from the use of this software.
//
// Permission is granted to anyone to use this software for any purpose,
// including commercial applications, and to alter it and redistribute it freely,
// subject to the following restrictions:
//
// 1. The origin of this software must not be misrepresented;
// you must not claim that you wrote the original software.
// If you use this software in a product, an acknowledgment
// in the product documentation would be appreciated but is not required.
//
// 2. Altered source versions must be plainly marked as such,
// and must not be misrepresented as being the original software.
//
// 3. This notice may not be removed or altered from any source distribution.
//
////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////
// Headers
////////////////////////////////////////////////////////////
#include <SFML/System/Vector2.hpp> // NOLINT(misc-header-include-cycle)
#include <cassert>
namespace sf
{
////////////////////////////////////////////////////////////
#if defined(__GNUC__)
#pragma GCC diagnostic push
#pragma GCC diagnostic ignored "-Wshadow"
#endif
template <typename T>
constexpr Vector2<T>::Vector2(T x, T y) : x(x), y(y)
{
}
#if defined(__GNUC__)
#pragma GCC diagnostic pop
#endif
////////////////////////////////////////////////////////////
template <typename T>
template <typename U>
constexpr Vector2<T>::operator Vector2<U>() const
{
return Vector2<U>(static_cast<U>(x), static_cast<U>(y));
}
////////////////////////////////////////////////////////////
template <typename T>
constexpr T Vector2<T>::lengthSquared() const
{
return dot(*this);
}
////////////////////////////////////////////////////////////
template <typename T>
constexpr Vector2<T> Vector2<T>::perpendicular() const
{
return Vector2<T>(-y, x);
}
////////////////////////////////////////////////////////////
template <typename T>
constexpr T Vector2<T>::dot(Vector2<T> rhs) const
{
return x * rhs.x + y * rhs.y;
}
////////////////////////////////////////////////////////////
template <typename T>
constexpr T Vector2<T>::cross(Vector2<T> rhs) const
{
return x * rhs.y - y * rhs.x;
}
////////////////////////////////////////////////////////////
template <typename T>
constexpr Vector2<T> Vector2<T>::componentWiseMul(Vector2<T> rhs) const
{
return Vector2<T>(x * rhs.x, y * rhs.y);
}
////////////////////////////////////////////////////////////
template <typename T>
constexpr Vector2<T> Vector2<T>::componentWiseDiv(Vector2<T> rhs) const
{
assert(rhs.x != 0 && "Vector2::componentWiseDiv() cannot divide by 0");
assert(rhs.y != 0 && "Vector2::componentWiseDiv() cannot divide by 0");
return Vector2<T>(x / rhs.x, y / rhs.y);
}
////////////////////////////////////////////////////////////
template <typename T>
constexpr Vector2<T> operator-(Vector2<T> right)
{
return Vector2<T>(-right.x, -right.y);
}
////////////////////////////////////////////////////////////
template <typename T>
constexpr Vector2<T>& operator+=(Vector2<T>& left, Vector2<T> right)
{
left.x += right.x;
left.y += right.y;
return left;
}
////////////////////////////////////////////////////////////
template <typename T>
constexpr Vector2<T>& operator-=(Vector2<T>& left, Vector2<T> right)
{
left.x -= right.x;
left.y -= right.y;
return left;
}
////////////////////////////////////////////////////////////
template <typename T>
constexpr Vector2<T> operator+(Vector2<T> left, Vector2<T> right)
{
return Vector2<T>(left.x + right.x, left.y + right.y);
}
////////////////////////////////////////////////////////////
template <typename T>
constexpr Vector2<T> operator-(Vector2<T> left, Vector2<T> right)
{
return Vector2<T>(left.x - right.x, left.y - right.y);
}
////////////////////////////////////////////////////////////
template <typename T>
constexpr Vector2<T> operator*(Vector2<T> left, T right)
{
return Vector2<T>(left.x * right, left.y * right);
}
////////////////////////////////////////////////////////////
template <typename T>
constexpr Vector2<T> operator*(T left, Vector2<T> right)
{
return Vector2<T>(right.x * left, right.y * left);
}
////////////////////////////////////////////////////////////
template <typename T>
constexpr Vector2<T>& operator*=(Vector2<T>& left, T right)
{
left.x *= right;
left.y *= right;
return left;
}
////////////////////////////////////////////////////////////
template <typename T>
constexpr Vector2<T> operator/(Vector2<T> left, T right)
{
assert(right != 0 && "Vector2::operator/ cannot divide by 0");
return Vector2<T>(left.x / right, left.y / right);
}
////////////////////////////////////////////////////////////
template <typename T>
constexpr Vector2<T>& operator/=(Vector2<T>& left, T right)
{
assert(right != 0 && "Vector2::operator/= cannot divide by 0");
left.x /= right;
left.y /= right;
return left;
}
////////////////////////////////////////////////////////////
template <typename T>
constexpr bool operator==(Vector2<T> left, Vector2<T> right)
{
return (left.x == right.x) && (left.y == right.y);
}
////////////////////////////////////////////////////////////
template <typename T>
constexpr bool operator!=(Vector2<T> left, Vector2<T> right)
{
return !(left == right);
}
} // namespace sf

View File

@ -1,356 +0,0 @@
////////////////////////////////////////////////////////////
//
// SFML - Simple and Fast Multimedia Library
// Copyright (C) 2007-2025 Laurent Gomila (laurent@sfml-dev.org)
//
// This software is provided 'as-is', without any express or implied warranty.
// In no event will the authors be held liable for any damages arising from the use of this software.
//
// Permission is granted to anyone to use this software for any purpose,
// including commercial applications, and to alter it and redistribute it freely,
// subject to the following restrictions:
//
// 1. The origin of this software must not be misrepresented;
// you must not claim that you wrote the original software.
// If you use this software in a product, an acknowledgment
// in the product documentation would be appreciated but is not required.
//
// 2. Altered source versions must be plainly marked as such,
// and must not be misrepresented as being the original software.
//
// 3. This notice may not be removed or altered from any source distribution.
//
////////////////////////////////////////////////////////////
#pragma once
#include <SFML/System/Export.hpp>
namespace sf
{
////////////////////////////////////////////////////////////
/// \brief Utility template class for manipulating
/// 3-dimensional vectors
///
////////////////////////////////////////////////////////////
template <typename T>
class Vector3
{
public:
////////////////////////////////////////////////////////////
/// \brief Default constructor
///
/// Creates a `Vector3(0, 0, 0)`.
///
////////////////////////////////////////////////////////////
constexpr Vector3() = default;
////////////////////////////////////////////////////////////
/// \brief Construct the vector from its coordinates
///
/// \param x X coordinate
/// \param y Y coordinate
/// \param z Z coordinate
///
////////////////////////////////////////////////////////////
constexpr Vector3(T x, T y, T z);
////////////////////////////////////////////////////////////
/// \brief Converts the vector to another type of vector
///
////////////////////////////////////////////////////////////
template <typename U>
constexpr explicit operator Vector3<U>() const;
////////////////////////////////////////////////////////////
/// \brief Length of the vector <i><b>(floating-point)</b></i>.
///
/// If you are not interested in the actual length, but only in comparisons, consider using `lengthSquared()`.
///
////////////////////////////////////////////////////////////
[[nodiscard]] SFML_SYSTEM_API T length() const;
////////////////////////////////////////////////////////////
/// \brief Square of vector's length.
///
/// Suitable for comparisons, more efficient than `length()`.
///
////////////////////////////////////////////////////////////
[[nodiscard]] constexpr T lengthSquared() const;
////////////////////////////////////////////////////////////
/// \brief Vector with same direction but length 1 <i><b>(floating-point)</b></i>.
///
/// \pre `*this` is no zero vector.
///
////////////////////////////////////////////////////////////
[[nodiscard]] SFML_SYSTEM_API Vector3 normalized() const;
////////////////////////////////////////////////////////////
/// \brief Dot product of two 3D vectors.
///
////////////////////////////////////////////////////////////
[[nodiscard]] constexpr T dot(const Vector3& rhs) const;
////////////////////////////////////////////////////////////
/// \brief Cross product of two 3D vectors.
///
////////////////////////////////////////////////////////////
[[nodiscard]] constexpr Vector3 cross(const Vector3& rhs) const;
////////////////////////////////////////////////////////////
/// \brief Component-wise multiplication of `*this` and `rhs`.
///
/// Computes `(lhs.x*rhs.x, lhs.y*rhs.y, lhs.z*rhs.z)`.
///
/// Scaling is the most common use case for component-wise multiplication/division.
/// This operation is also known as the Hadamard or Schur product.
///
////////////////////////////////////////////////////////////
[[nodiscard]] constexpr Vector3 componentWiseMul(const Vector3& rhs) const;
////////////////////////////////////////////////////////////
/// \brief Component-wise division of `*this` and `rhs`.
///
/// Computes `(lhs.x/rhs.x, lhs.y/rhs.y, lhs.z/rhs.z)`.
///
/// Scaling is the most common use case for component-wise multiplication/division.
///
/// \pre Neither component of `rhs` is zero.
///
////////////////////////////////////////////////////////////
[[nodiscard]] constexpr Vector3 componentWiseDiv(const Vector3& rhs) const;
////////////////////////////////////////////////////////////
// Member data
////////////////////////////////////////////////////////////
T x{}; //!< X coordinate of the vector
T y{}; //!< Y coordinate of the vector
T z{}; //!< Z coordinate of the vector
};
////////////////////////////////////////////////////////////
/// \relates Vector3
/// \brief Overload of unary `operator-`
///
/// \param left Vector to negate
///
/// \return Member-wise opposite of the vector
///
////////////////////////////////////////////////////////////
template <typename T>
[[nodiscard]] constexpr Vector3<T> operator-(const Vector3<T>& left);
////////////////////////////////////////////////////////////
/// \relates Vector3
/// \brief Overload of binary `operator+=`
///
/// This operator performs a member-wise addition of both vectors,
/// and assigns the result to `left`.
///
/// \param left Left operand (a vector)
/// \param right Right operand (a vector)
///
/// \return Reference to `left`
///
////////////////////////////////////////////////////////////
template <typename T>
constexpr Vector3<T>& operator+=(Vector3<T>& left, const Vector3<T>& right);
////////////////////////////////////////////////////////////
/// \relates Vector3
/// \brief Overload of binary `operator-=`
///
/// This operator performs a member-wise subtraction of both vectors,
/// and assigns the result to `left`.
///
/// \param left Left operand (a vector)
/// \param right Right operand (a vector)
///
/// \return Reference to `left`
///
////////////////////////////////////////////////////////////
template <typename T>
constexpr Vector3<T>& operator-=(Vector3<T>& left, const Vector3<T>& right);
////////////////////////////////////////////////////////////
/// \relates Vector3
/// \brief Overload of binary `operator+`
///
/// \param left Left operand (a vector)
/// \param right Right operand (a vector)
///
/// \return Member-wise addition of both vectors
///
////////////////////////////////////////////////////////////
template <typename T>
[[nodiscard]] constexpr Vector3<T> operator+(const Vector3<T>& left, const Vector3<T>& right);
////////////////////////////////////////////////////////////
/// \relates Vector3
/// \brief Overload of binary `operator-`
///
/// \param left Left operand (a vector)
/// \param right Right operand (a vector)
///
/// \return Member-wise subtraction of both vectors
///
////////////////////////////////////////////////////////////
template <typename T>
[[nodiscard]] constexpr Vector3<T> operator-(const Vector3<T>& left, const Vector3<T>& right);
////////////////////////////////////////////////////////////
/// \relates Vector3
/// \brief Overload of binary `operator*`
///
/// \param left Left operand (a vector)
/// \param right Right operand (a scalar value)
///
/// \return Member-wise multiplication by `right`
///
////////////////////////////////////////////////////////////
template <typename T>
[[nodiscard]] constexpr Vector3<T> operator*(const Vector3<T>& left, T right);
////////////////////////////////////////////////////////////
/// \relates Vector3
/// \brief Overload of binary `operator*`
///
/// \param left Left operand (a scalar value)
/// \param right Right operand (a vector)
///
/// \return Member-wise multiplication by `left`
///
////////////////////////////////////////////////////////////
template <typename T>
[[nodiscard]] constexpr Vector3<T> operator*(T left, const Vector3<T>& right);
////////////////////////////////////////////////////////////
/// \relates Vector3
/// \brief Overload of binary `operator*=`
///
/// This operator performs a member-wise multiplication by `right`,
/// and assigns the result to `left`.
///
/// \param left Left operand (a vector)
/// \param right Right operand (a scalar value)
///
/// \return Reference to `left`
///
////////////////////////////////////////////////////////////
template <typename T>
constexpr Vector3<T>& operator*=(Vector3<T>& left, T right);
////////////////////////////////////////////////////////////
/// \relates Vector3
/// \brief Overload of binary `operator/`
///
/// \param left Left operand (a vector)
/// \param right Right operand (a scalar value)
///
/// \return Member-wise division by `right`
///
////////////////////////////////////////////////////////////
template <typename T>
[[nodiscard]] constexpr Vector3<T> operator/(const Vector3<T>& left, T right);
////////////////////////////////////////////////////////////
/// \relates Vector3
/// \brief Overload of binary `operator/=`
///
/// This operator performs a member-wise division by `right`,
/// and assigns the result to `left`.
///
/// \param left Left operand (a vector)
/// \param right Right operand (a scalar value)
///
/// \return Reference to `left`
///
////////////////////////////////////////////////////////////
template <typename T>
constexpr Vector3<T>& operator/=(Vector3<T>& left, T right);
////////////////////////////////////////////////////////////
/// \relates Vector3
/// \brief Overload of binary `operator==`
///
/// This operator compares strict equality between two vectors.
///
/// \param left Left operand (a vector)
/// \param right Right operand (a vector)
///
/// \return `true` if `left` is equal to `right`
///
////////////////////////////////////////////////////////////
template <typename T>
[[nodiscard]] constexpr bool operator==(const Vector3<T>& left, const Vector3<T>& right);
////////////////////////////////////////////////////////////
/// \relates Vector3
/// \brief Overload of binary `operator!=`
///
/// This operator compares strict difference between two vectors.
///
/// \param left Left operand (a vector)
/// \param right Right operand (a vector)
///
/// \return `true` if `left` is not equal to `right`
///
////////////////////////////////////////////////////////////
template <typename T>
[[nodiscard]] constexpr bool operator!=(const Vector3<T>& left, const Vector3<T>& right);
// Aliases for the most common types
using Vector3i = Vector3<int>;
using Vector3f = Vector3<float>;
} // namespace sf
#include <SFML/System/Vector3.inl>
////////////////////////////////////////////////////////////
/// \class sf::Vector3
/// \ingroup system
///
/// `sf::Vector3` is a simple class that defines a mathematical
/// vector with three coordinates (x, y and z). It can be used to
/// represent anything that has three dimensions: a size, a point,
/// a velocity, etc.
///
/// The template parameter T is the type of the coordinates. It
/// can be any type that supports arithmetic operations (+, -, /, *)
/// and comparisons (==, !=), for example int or float.
/// Note that some operations are only meaningful for vectors where T is
/// a floating point type (e.g. float or double), often because
/// results cannot be represented accurately with integers.
/// The method documentation mentions "(floating-point)" in those cases.
///
/// You generally don't have to care about the templated form (`sf::Vector3<T>`),
/// the most common specializations have special type aliases:
/// \li `sf::Vector3<float>` is `sf::Vector3f`
/// \li `sf::Vector3<int>` is `sf::Vector3i`
///
/// The `sf::Vector3` class has a small and simple interface, its x, y and z members
/// can be accessed directly (there are no accessors like `setX()`, `getX()`).
///
/// Usage example:
/// \code
/// sf::Vector3f v(16.5f, 24.f, -3.2f);
/// v.x = 18.2f;
/// float y = v.y;
///
/// sf::Vector3f w = v * 5.f;
/// sf::Vector3f u;
/// u = v + w;
///
/// float s = v.dot(w);
/// sf::Vector3f t = v.cross(w);
///
/// bool different = (v != u);
/// \endcode
///
/// Note: for 2-dimensional vectors, see `sf::Vector2`.
///
////////////////////////////////////////////////////////////

View File

@ -1,214 +0,0 @@
////////////////////////////////////////////////////////////
//
// SFML - Simple and Fast Multimedia Library
// Copyright (C) 2007-2025 Laurent Gomila (laurent@sfml-dev.org)
//
// This software is provided 'as-is', without any express or implied warranty.
// In no event will the authors be held liable for any damages arising from the use of this software.
//
// Permission is granted to anyone to use this software for any purpose,
// including commercial applications, and to alter it and redistribute it freely,
// subject to the following restrictions:
//
// 1. The origin of this software must not be misrepresented;
// you must not claim that you wrote the original software.
// If you use this software in a product, an acknowledgment
// in the product documentation would be appreciated but is not required.
//
// 2. Altered source versions must be plainly marked as such,
// and must not be misrepresented as being the original software.
//
// 3. This notice may not be removed or altered from any source distribution.
//
////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////
// Headers
////////////////////////////////////////////////////////////
#include <SFML/System/Vector3.hpp> // NOLINT(misc-header-include-cycle)
#include <cassert>
namespace sf
{
////////////////////////////////////////////////////////////
#if defined(__GNUC__)
#pragma GCC diagnostic push
#pragma GCC diagnostic ignored "-Wshadow"
#endif
template <typename T>
constexpr Vector3<T>::Vector3(T x, T y, T z) : x(x), y(y), z(z)
{
}
#if defined(__GNUC__)
#pragma GCC diagnostic pop
#endif
////////////////////////////////////////////////////////////
template <typename T>
template <typename U>
constexpr Vector3<T>::operator Vector3<U>() const
{
return Vector3<U>(static_cast<U>(x), static_cast<U>(y), static_cast<U>(z));
}
////////////////////////////////////////////////////////////
template <typename T>
constexpr T Vector3<T>::lengthSquared() const
{
return dot(*this);
}
////////////////////////////////////////////////////////////
template <typename T>
constexpr T Vector3<T>::dot(const Vector3<T>& rhs) const
{
return x * rhs.x + y * rhs.y + z * rhs.z;
}
////////////////////////////////////////////////////////////
template <typename T>
constexpr Vector3<T> Vector3<T>::cross(const Vector3<T>& rhs) const
{
return Vector3<T>((y * rhs.z) - (z * rhs.y), (z * rhs.x) - (x * rhs.z), (x * rhs.y) - (y * rhs.x));
}
////////////////////////////////////////////////////////////
template <typename T>
constexpr Vector3<T> Vector3<T>::componentWiseMul(const Vector3<T>& rhs) const
{
return Vector3<T>(x * rhs.x, y * rhs.y, z * rhs.z);
}
////////////////////////////////////////////////////////////
template <typename T>
constexpr Vector3<T> Vector3<T>::componentWiseDiv(const Vector3<T>& rhs) const
{
assert(rhs.x != 0 && "Vector3::componentWiseDiv() cannot divide by 0");
assert(rhs.y != 0 && "Vector3::componentWiseDiv() cannot divide by 0");
assert(rhs.z != 0 && "Vector3::componentWiseDiv() cannot divide by 0");
return Vector3<T>(x / rhs.x, y / rhs.y, z / rhs.z);
}
////////////////////////////////////////////////////////////
template <typename T>
constexpr Vector3<T> operator-(const Vector3<T>& left)
{
return Vector3<T>(-left.x, -left.y, -left.z);
}
////////////////////////////////////////////////////////////
template <typename T>
constexpr Vector3<T>& operator+=(Vector3<T>& left, const Vector3<T>& right)
{
left.x += right.x;
left.y += right.y;
left.z += right.z;
return left;
}
////////////////////////////////////////////////////////////
template <typename T>
constexpr Vector3<T>& operator-=(Vector3<T>& left, const Vector3<T>& right)
{
left.x -= right.x;
left.y -= right.y;
left.z -= right.z;
return left;
}
////////////////////////////////////////////////////////////
template <typename T>
constexpr Vector3<T> operator+(const Vector3<T>& left, const Vector3<T>& right)
{
return Vector3<T>(left.x + right.x, left.y + right.y, left.z + right.z);
}
////////////////////////////////////////////////////////////
template <typename T>
constexpr Vector3<T> operator-(const Vector3<T>& left, const Vector3<T>& right)
{
return Vector3<T>(left.x - right.x, left.y - right.y, left.z - right.z);
}
////////////////////////////////////////////////////////////
template <typename T>
constexpr Vector3<T> operator*(const Vector3<T>& left, T right)
{
return Vector3<T>(left.x * right, left.y * right, left.z * right);
}
////////////////////////////////////////////////////////////
template <typename T>
constexpr Vector3<T> operator*(T left, const Vector3<T>& right)
{
return Vector3<T>(right.x * left, right.y * left, right.z * left);
}
////////////////////////////////////////////////////////////
template <typename T>
constexpr Vector3<T>& operator*=(Vector3<T>& left, T right)
{
left.x *= right;
left.y *= right;
left.z *= right;
return left;
}
////////////////////////////////////////////////////////////
template <typename T>
constexpr Vector3<T> operator/(const Vector3<T>& left, T right)
{
assert(right != 0 && "Vector3::operator/ cannot divide by 0");
return Vector3<T>(left.x / right, left.y / right, left.z / right);
}
////////////////////////////////////////////////////////////
template <typename T>
constexpr Vector3<T>& operator/=(Vector3<T>& left, T right)
{
assert(right != 0 && "Vector3::operator/= cannot divide by 0");
left.x /= right;
left.y /= right;
left.z /= right;
return left;
}
////////////////////////////////////////////////////////////
template <typename T>
constexpr bool operator==(const Vector3<T>& left, const Vector3<T>& right)
{
return (left.x == right.x) && (left.y == right.y) && (left.z == right.z);
}
////////////////////////////////////////////////////////////
template <typename T>
constexpr bool operator!=(const Vector3<T>& left, const Vector3<T>& right)
{
return !(left == right);
}
} // namespace sf

View File

@ -1,55 +0,0 @@
////////////////////////////////////////////////////////////
//
// SFML - Simple and Fast Multimedia Library
// Copyright (C) 2007-2025 Laurent Gomila (laurent@sfml-dev.org)
//
// This software is provided 'as-is', without any express or implied warranty.
// In no event will the authors be held liable for any damages arising from the use of this software.
//
// Permission is granted to anyone to use this software for any purpose,
// including commercial applications, and to alter it and redistribute it freely,
// subject to the following restrictions:
//
// 1. The origin of this software must not be misrepresented;
// you must not claim that you wrote the original software.
// If you use this software in a product, an acknowledgment
// in the product documentation would be appreciated but is not required.
//
// 2. Altered source versions must be plainly marked as such,
// and must not be misrepresented as being the original software.
//
// 3. This notice may not be removed or altered from any source distribution.
//
////////////////////////////////////////////////////////////
#pragma once
////////////////////////////////////////////////////////////
// Headers
////////////////////////////////////////////////////////////
#include <SFML/Window/Clipboard.hpp>
#include <SFML/Window/Context.hpp>
#include <SFML/Window/ContextSettings.hpp>
#include <SFML/Window/Cursor.hpp>
#include <SFML/Window/Event.hpp>
#include <SFML/Window/Joystick.hpp>
#include <SFML/Window/Keyboard.hpp>
#include <SFML/Window/Mouse.hpp>
#include <SFML/Window/Sensor.hpp>
#include <SFML/Window/Touch.hpp>
#include <SFML/Window/VideoMode.hpp>
#include <SFML/Window/Window.hpp>
#include <SFML/Window/WindowEnums.hpp>
#include <SFML/Window/WindowHandle.hpp>
#include <SFML/System.hpp>
////////////////////////////////////////////////////////////
/// \defgroup window Window module
///
/// Provides OpenGL-based windows, and abstractions for
/// events and input handling.
///
////////////////////////////////////////////////////////////

View File

@ -1,114 +0,0 @@
////////////////////////////////////////////////////////////
//
// SFML - Simple and Fast Multimedia Library
// Copyright (C) 2007-2025 Laurent Gomila (laurent@sfml-dev.org)
//
// This software is provided 'as-is', without any express or implied warranty.
// In no event will the authors be held liable for any damages arising from the use of this software.
//
// Permission is granted to anyone to use this software for any purpose,
// including commercial applications, and to alter it and redistribute it freely,
// subject to the following restrictions:
//
// 1. The origin of this software must not be misrepresented;
// you must not claim that you wrote the original software.
// If you use this software in a product, an acknowledgment
// in the product documentation would be appreciated but is not required.
//
// 2. Altered source versions must be plainly marked as such,
// and must not be misrepresented as being the original software.
//
// 3. This notice may not be removed or altered from any source distribution.
//
////////////////////////////////////////////////////////////
#pragma once
////////////////////////////////////////////////////////////
// Headers
////////////////////////////////////////////////////////////
#include <SFML/Window/Export.hpp>
namespace sf
{
class String;
////////////////////////////////////////////////////////////
/// \brief Give access to the system clipboard
///
////////////////////////////////////////////////////////////
namespace Clipboard
{
////////////////////////////////////////////////////////////
/// \brief Get the content of the clipboard as string data
///
/// This function returns the content of the clipboard
/// as a string. If the clipboard does not contain string
/// it returns an empty `sf::String` object.
///
/// \return Clipboard contents as `sf::String` object
///
////////////////////////////////////////////////////////////
[[nodiscard]] SFML_WINDOW_API String getString();
////////////////////////////////////////////////////////////
/// \brief Set the content of the clipboard as string data
///
/// This function sets the content of the clipboard as a
/// string.
///
/// \warning Due to limitations on some operating systems,
/// setting the clipboard contents is only
/// guaranteed to work if there is currently an
/// open window for which events are being handled.
///
/// \param text `sf::String` containing the data to be sent
/// to the clipboard
///
////////////////////////////////////////////////////////////
SFML_WINDOW_API void setString(const String& text);
} // namespace Clipboard
} // namespace sf
////////////////////////////////////////////////////////////
/// \namespace sf::Clipboard
/// \ingroup window
///
/// `sf::Clipboard` provides an interface for getting and
/// setting the contents of the system clipboard.
///
/// It is important to note that due to limitations on some
/// operating systems, setting the clipboard contents is
/// only guaranteed to work if there is currently an open
/// window for which events are being handled.
///
/// Usage example:
/// \code
/// // get the clipboard content as a string
/// sf::String string = sf::Clipboard::getString();
///
/// // or use it in the event loop
/// while (const std::optional event = window.pollEvent())
/// {
/// if (event->is<sf::Event::Closed>())
/// window.close();
///
/// if (const auto* keyPressed = event->getIf<sf::Event::KeyPressed>())
/// {
/// // Using Ctrl + V to paste a string into SFML
/// if (keyPressed->control && keyPressed->code == sf::Keyboard::Key::V)
/// string = sf::Clipboard::getString();
///
/// // Using Ctrl + C to copy a string out of SFML
/// if (keyPressed->control && keyPressed->code == sf::Keyboard::Key::C)
/// sf::Clipboard::setString("Hello World!");
/// }
/// }
/// \endcode
///
/// \see `sf::String`, `sf::Event`
///
////////////////////////////////////////////////////////////

Some files were not shown because too many files have changed in this diff Show More