From a4e1362c5d45dfc5d7ba3bc2a4d5927e5ab874d2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Lukas=20D=C3=BCrrenberger?= Date: Wed, 14 Jan 2026 10:39:11 +0100 Subject: [PATCH 1/7] Update CSFML to 3.0.0 --- SFML.Module.props | 2 +- readme.md | 6 +----- 2 files changed, 2 insertions(+), 6 deletions(-) diff --git a/SFML.Module.props b/SFML.Module.props index 18f8f655..6117e69b 100644 --- a/SFML.Module.props +++ b/SFML.Module.props @@ -18,7 +18,7 @@ - + diff --git a/readme.md b/readme.md index d20c27e2..ff220ece 100644 --- a/readme.md +++ b/readme.md @@ -7,11 +7,7 @@ The network module is not provided in the SFML.Net binding as .NET provides supe ## State of Development -Development is focused on the next major version in the `master` branch. No more features are planned for the 2.x release series. - -* The [`master`](https://github.com/SFML/SFML.Net/tree/master) branch contains work in progress for the next major version SFML.Net 3. As such it's considered unstable, but any testing and feedback is highly appreciated. -* The [`2.6.0`](https://github.com/SFML/SFML.Net/tree/2.6.0) tag is the latest official SFML.Net release and will be the last minor release in the 2.x series. -* The [`2.6.x`](https://github.com/SFML/SFML.Net/tree/2.6.x) contains the latest bugfix work on SFML.Net 2.6.x, matching CSFML's and SFML's `2.6.x` branches. +Development is focused on version 3 in the `master` branch. No more features are planned for the 2.x release series. ## Authors From d756acaffeae8b533723566da8f10490d91d8062 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Lukas=20D=C3=BCrrenberger?= Date: Wed, 14 Jan 2026 10:50:32 +0100 Subject: [PATCH 2/7] Update test dependencies --- SFML.NuGet.props | 2 +- test/SFML.System.Test/SFML.System.Test.csproj | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/SFML.NuGet.props b/SFML.NuGet.props index e7364163..ce5c78b1 100644 --- a/SFML.NuGet.props +++ b/SFML.NuGet.props @@ -20,7 +20,7 @@ - + diff --git a/test/SFML.System.Test/SFML.System.Test.csproj b/test/SFML.System.Test/SFML.System.Test.csproj index 4eb7ad1b..69189584 100644 --- a/test/SFML.System.Test/SFML.System.Test.csproj +++ b/test/SFML.System.Test/SFML.System.Test.csproj @@ -15,9 +15,9 @@ all runtime; build; native; contentfiles; analyzers; buildtransitive - + - + all runtime; build; native; contentfiles; analyzers; buildtransitive From 536ed3bed2665e1f93f03b6ed578e897d4ca2ea6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Lukas=20D=C3=BCrrenberger?= Date: Wed, 14 Jan 2026 12:37:49 +0100 Subject: [PATCH 3/7] Use C# language version 12 --- .editorconfig | 5 + SFML.Module.props | 2 + src/SFML.Audio/Cone.cs | 101 +- src/SFML.Audio/EffectProcessor.cs | 171 +- src/SFML.Audio/Listener.cs | 239 ++- src/SFML.Audio/Music.cs | 1261 +++++++------ src/SFML.Audio/Sound.cs | 1011 +++++----- src/SFML.Audio/SoundBuffer.cs | 437 +++-- src/SFML.Audio/SoundBufferRecorder.cs | 131 +- src/SFML.Audio/SoundChannel.cs | 76 +- src/SFML.Audio/SoundRecorder.cs | 579 +++--- src/SFML.Audio/SoundStream.cs | 1189 ++++++------ src/SFML.Graphics/BlendMode.cs | 399 ++-- src/SFML.Graphics/CircleShape.cs | 211 ++- src/SFML.Graphics/Color.cs | 407 ++-- src/SFML.Graphics/ConvexShape.cs | 161 +- src/SFML.Graphics/CoordinateType.cs | 21 +- src/SFML.Graphics/Font.cs | 569 +++--- src/SFML.Graphics/Glsl.cs | 888 +++++---- src/SFML.Graphics/Glyph.cs | 31 +- src/SFML.Graphics/IDrawable.cs | 31 +- src/SFML.Graphics/IRenderTarget.cs | 613 ++++--- src/SFML.Graphics/Image.cs | 661 ++++--- src/SFML.Graphics/PrimitiveType.cs | 53 +- src/SFML.Graphics/Rect.cs | 789 ++++---- src/SFML.Graphics/RectangleShape.cs | 174 +- src/SFML.Graphics/RenderStates.cs | 273 ++- src/SFML.Graphics/RenderTexture.cs | 1029 ++++++----- src/SFML.Graphics/RenderWindow.cs | 1621 ++++++++-------- src/SFML.Graphics/Shader.cs | 1075 ++++++----- src/SFML.Graphics/Shape.cs | 487 +++-- src/SFML.Graphics/Sprite.cs | 337 ++-- src/SFML.Graphics/StencilMode.cs | 337 ++-- src/SFML.Graphics/Text.cs | 694 ++++--- src/SFML.Graphics/Texture.cs | 1017 +++++----- src/SFML.Graphics/Transform.cs | 449 +++-- src/SFML.Graphics/Transformable.cs | 325 ++-- src/SFML.Graphics/Vertex.cs | 139 +- src/SFML.Graphics/VertexArray.cs | 359 ++-- src/SFML.Graphics/VertexBuffer.cs | 667 ++++--- src/SFML.Graphics/View.cs | 421 +++-- src/SFML.System/Allocation.cs | 33 +- src/SFML.System/Angle.cs | 647 ++++--- src/SFML.System/Buffer.cs | 121 +- src/SFML.System/Clock.cs | 191 +- src/SFML.System/LoadingFailedException.cs | 129 +- src/SFML.System/ObjectBase.cs | 158 +- src/SFML.System/SharedLibName.cs | 25 +- src/SFML.System/StreamAdaptor.cs | 338 ++-- src/SFML.System/Time.cs | 513 +++--- src/SFML.System/Vector2.cs | 1629 ++++++++--------- src/SFML.System/Vector3.cs | 455 +++-- src/SFML.Window/Clipboard.cs | 65 +- src/SFML.Window/Context.cs | 186 +- src/SFML.Window/ContextSettings.cs | 187 +- src/SFML.Window/Cursor.cs | 451 +++-- src/SFML.Window/Event.cs | 639 ++++--- src/SFML.Window/EventArgs.cs | 697 ++++--- src/SFML.Window/Joystick.cs | 329 ++-- src/SFML.Window/Keyboard.cs | 1277 +++++++------ src/SFML.Window/LoadingFailedException.cs | 135 +- src/SFML.Window/Mouse.cs | 241 ++- src/SFML.Window/Sensor.cs | 125 +- src/SFML.Window/Touch.cs | 89 +- src/SFML.Window/VideoMode.cs | 359 ++-- src/SFML.Window/Vulkan.cs | 109 +- src/SFML.Window/Window.cs | 973 +++++----- src/SFML.Window/WindowBase.cs | 1149 ++++++------ test/SFML.System.Test/SFML.System.Test.csproj | 1 + test/SFML.System.Test/Vector2f.test.cs | 12 +- test/SFML.System.Test/Vector2i.test.cs | 16 +- test/SFML.System.Test/Vector2u.test.cs | 16 +- 72 files changed, 15312 insertions(+), 15423 deletions(-) diff --git a/.editorconfig b/.editorconfig index 93d1f029..ab752011 100644 --- a/.editorconfig +++ b/.editorconfig @@ -125,6 +125,11 @@ dotnet_style_prefer_conditional_expression_over_return = false:suggestion dotnet_style_coalesce_expression = true:warning dotnet_style_null_propagation = true:warning +# Use primary constructor +# https://learn.microsoft.com/dotnet/fundamentals/code-analysis/style-rules/ide0290 +dotnet_style_prefer_primary_constructors = false +dotnet_diagnostic.IDE0290.severity = silent + # C# Code Style Settings [*.{cs,csx,cake}] diff --git a/SFML.Module.props b/SFML.Module.props index 6117e69b..665c81b4 100644 --- a/SFML.Module.props +++ b/SFML.Module.props @@ -6,6 +6,8 @@ + 12 + true true diff --git a/src/SFML.Audio/Cone.cs b/src/SFML.Audio/Cone.cs index 93eb236f..aac8468a 100644 --- a/src/SFML.Audio/Cone.cs +++ b/src/SFML.Audio/Cone.cs @@ -1,64 +1,63 @@ using System.Runtime.InteropServices; using SFML.System; -namespace SFML.Audio +namespace SFML.Audio; + +//////////////////////////////////////////////////////////// +/// +/// Structure defining the properties of a directional cone +/// +/// When set on the listener, 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. +/// +/// When set on sound sources, they 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. +/// +//////////////////////////////////////////////////////////// +public struct Cone { - //////////////////////////////////////////////////////////// - /// - /// Structure defining the properties of a directional cone - /// - /// When set on the listener, 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. - /// - /// When set on sound sources, they 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. - /// - //////////////////////////////////////////////////////////// - public struct Cone - { - /// Inner angle - public Angle InnerAngle; + /// Inner angle + public Angle InnerAngle; - /// Outer angle - public Angle OuterAngle; + /// Outer angle + public Angle OuterAngle; - /// Outer angle - public float OuterGain; + /// Outer angle + public float OuterGain; - [StructLayout(LayoutKind.Sequential)] - internal struct MarshalData - { - public float InnerAngleDegrees; - public float OuterAngleDegrees; - public float OuterGain; - } + [StructLayout(LayoutKind.Sequential)] + internal struct MarshalData + { + public float InnerAngleDegrees; + public float OuterAngleDegrees; + public float OuterGain; + } - internal Cone(MarshalData data) - { - InnerAngle = Angle.FromDegrees(data.InnerAngleDegrees); - OuterAngle = Angle.FromDegrees(data.OuterAngleDegrees); - OuterGain = data.OuterGain; - } + internal Cone(MarshalData data) + { + InnerAngle = Angle.FromDegrees(data.InnerAngleDegrees); + OuterAngle = Angle.FromDegrees(data.OuterAngleDegrees); + OuterGain = data.OuterGain; + } - // Return a marshalled version of the instance, that can directly be passed to the C API - internal MarshalData Marshal() + // Return a marshalled version of the instance, that can directly be passed to the C API + internal MarshalData Marshal() + { + var data = new MarshalData { - var data = new MarshalData - { - InnerAngleDegrees = InnerAngle.Degrees, - OuterAngleDegrees = OuterAngle.Degrees, - OuterGain = OuterGain - }; + InnerAngleDegrees = InnerAngle.Degrees, + OuterAngleDegrees = OuterAngle.Degrees, + OuterGain = OuterGain + }; - return data; - } + return data; } } diff --git a/src/SFML.Audio/EffectProcessor.cs b/src/SFML.Audio/EffectProcessor.cs index 0d9be093..e54ddc57 100644 --- a/src/SFML.Audio/EffectProcessor.cs +++ b/src/SFML.Audio/EffectProcessor.cs @@ -2,90 +2,89 @@ using System.Runtime.InteropServices; using System; -namespace SFML.Audio -{ - //////////////////////////////////////////////////////////// - /// - /// 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. - /// - /// 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. - /// - //////////////////////////////////////////////////////////// - public delegate long EffectProcessor(float[] inputFrames, float[] outputFrames, uint frameChannelCount); +namespace SFML.Audio; - [UnmanagedFunctionPointer(CallingConvention.Cdecl)] - internal delegate long EffectProcessorInternal(IntPtr inputFrames, uint inputFrameCount, IntPtr outputFrames, uint outputFrameCount, uint frameChannelCount); -} \ No newline at end of file +//////////////////////////////////////////////////////////// +/// +/// 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. +/// +/// 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. +/// +//////////////////////////////////////////////////////////// +public delegate long EffectProcessor(float[] inputFrames, float[] outputFrames, uint frameChannelCount); + +[UnmanagedFunctionPointer(CallingConvention.Cdecl)] +internal delegate long EffectProcessorInternal(IntPtr inputFrames, uint inputFrameCount, IntPtr outputFrames, uint outputFrameCount, uint frameChannelCount); \ No newline at end of file diff --git a/src/SFML.Audio/Listener.cs b/src/SFML.Audio/Listener.cs index bef5f8ea..acb406a1 100644 --- a/src/SFML.Audio/Listener.cs +++ b/src/SFML.Audio/Listener.cs @@ -2,131 +2,130 @@ using System.Security; using SFML.System; -namespace SFML.Audio +namespace SFML.Audio; + +//////////////////////////////////////////////////////////// +/// +/// The audio listener is the point in the scene +/// from where all the sounds are heard +/// +//////////////////////////////////////////////////////////// +public static class Listener { //////////////////////////////////////////////////////////// /// - /// The audio listener is the point in the scene - /// from where all the sounds are heard + /// The 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). /// //////////////////////////////////////////////////////////// - public class Listener + public static float GlobalVolume { - //////////////////////////////////////////////////////////// - /// - /// The 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). - /// - //////////////////////////////////////////////////////////// - public static float GlobalVolume - { - get => sfListener_getGlobalVolume(); - set => sfListener_setGlobalVolume(value); - } - - //////////////////////////////////////////////////////////// - /// - /// 3D position of the listener (default is (0, 0, 0)) - /// - //////////////////////////////////////////////////////////// - public static Vector3f Position - { - get => sfListener_getPosition(); - set => sfListener_setPosition(value); - } - - //////////////////////////////////////////////////////////// - /// - /// 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). - /// - //////////////////////////////////////////////////////////// - public static Vector3f Direction - { - get => sfListener_getDirection(); - set => sfListener_setDirection(value); - } - - //////////////////////////////////////////////////////////// - /// - /// The velocity of the listener in the scene (default is (0, 0, -1)) - /// - //////////////////////////////////////////////////////////// - public static Vector3f Velocity - { - get => sfListener_getVelocity(); - set => sfListener_setVelocity(value); - } - - //////////////////////////////////////////////////////////// - /// - /// The cone defines how directional attenuation is applied. - /// The default cone of a sound is {2 * PI, 2 * PI, 1}. - /// - //////////////////////////////////////////////////////////// - public static Cone Cone - { - get => new Cone(sfListener_getCone()); - set => sfListener_setCone(value.Marshal()); - } - - //////////////////////////////////////////////////////////// - /// - /// 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. - /// - //////////////////////////////////////////////////////////// - public static Vector3f UpVector - { - get => sfListener_getUpVector(); - set => sfListener_setUpVector(value); - } - - #region Imports - [DllImport(CSFML.Audio, CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] - private static extern void sfListener_setGlobalVolume(float volume); - - [DllImport(CSFML.Audio, CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] - private static extern float sfListener_getGlobalVolume(); - - [DllImport(CSFML.Audio, CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] - private static extern void sfListener_setPosition(Vector3f position); - - [DllImport(CSFML.Audio, CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] - private static extern Vector3f sfListener_getPosition(); - - [DllImport(CSFML.Audio, CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] - private static extern void sfListener_setDirection(Vector3f direction); - - [DllImport(CSFML.Audio, CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] - private static extern Vector3f sfListener_getDirection(); - - [DllImport(CSFML.Audio, CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] - private static extern void sfListener_setVelocity(Vector3f direction); - - [DllImport(CSFML.Audio, CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] - private static extern Vector3f sfListener_getVelocity(); - - [DllImport(CSFML.Audio, CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] - private static extern void sfListener_setCone(Cone.MarshalData cone); - - [DllImport(CSFML.Audio, CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] - private static extern Cone.MarshalData sfListener_getCone(); - - [DllImport(CSFML.Audio, CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] - private static extern void sfListener_setUpVector(Vector3f upVector); - - [DllImport(CSFML.Audio, CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] - private static extern Vector3f sfListener_getUpVector(); - #endregion + get => sfListener_getGlobalVolume(); + set => sfListener_setGlobalVolume(value); } + + //////////////////////////////////////////////////////////// + /// + /// 3D position of the listener (default is (0, 0, 0)) + /// + //////////////////////////////////////////////////////////// + public static Vector3f Position + { + get => sfListener_getPosition(); + set => sfListener_setPosition(value); + } + + //////////////////////////////////////////////////////////// + /// + /// 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). + /// + //////////////////////////////////////////////////////////// + public static Vector3f Direction + { + get => sfListener_getDirection(); + set => sfListener_setDirection(value); + } + + //////////////////////////////////////////////////////////// + /// + /// The velocity of the listener in the scene (default is (0, 0, -1)) + /// + //////////////////////////////////////////////////////////// + public static Vector3f Velocity + { + get => sfListener_getVelocity(); + set => sfListener_setVelocity(value); + } + + //////////////////////////////////////////////////////////// + /// + /// The cone defines how directional attenuation is applied. + /// The default cone of a sound is {2 * PI, 2 * PI, 1}. + /// + //////////////////////////////////////////////////////////// + public static Cone Cone + { + get => new(sfListener_getCone()); + set => sfListener_setCone(value.Marshal()); + } + + //////////////////////////////////////////////////////////// + /// + /// 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. + /// + //////////////////////////////////////////////////////////// + public static Vector3f UpVector + { + get => sfListener_getUpVector(); + set => sfListener_setUpVector(value); + } + + #region Imports + [DllImport(CSFML.Audio, CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] + private static extern void sfListener_setGlobalVolume(float volume); + + [DllImport(CSFML.Audio, CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] + private static extern float sfListener_getGlobalVolume(); + + [DllImport(CSFML.Audio, CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] + private static extern void sfListener_setPosition(Vector3f position); + + [DllImport(CSFML.Audio, CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] + private static extern Vector3f sfListener_getPosition(); + + [DllImport(CSFML.Audio, CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] + private static extern void sfListener_setDirection(Vector3f direction); + + [DllImport(CSFML.Audio, CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] + private static extern Vector3f sfListener_getDirection(); + + [DllImport(CSFML.Audio, CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] + private static extern void sfListener_setVelocity(Vector3f direction); + + [DllImport(CSFML.Audio, CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] + private static extern Vector3f sfListener_getVelocity(); + + [DllImport(CSFML.Audio, CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] + private static extern void sfListener_setCone(Cone.MarshalData cone); + + [DllImport(CSFML.Audio, CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] + private static extern Cone.MarshalData sfListener_getCone(); + + [DllImport(CSFML.Audio, CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] + private static extern void sfListener_setUpVector(Vector3f upVector); + + [DllImport(CSFML.Audio, CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] + private static extern Vector3f sfListener_getUpVector(); + #endregion } diff --git a/src/SFML.Audio/Music.cs b/src/SFML.Audio/Music.cs index 18992992..3f587630 100644 --- a/src/SFML.Audio/Music.cs +++ b/src/SFML.Audio/Music.cs @@ -4,753 +4,752 @@ using System.Security; using SFML.System; -namespace SFML.Audio +namespace SFML.Audio; + +//////////////////////////////////////////////////////////// +/// +/// Streamed music played from an audio file +/// +//////////////////////////////////////////////////////////// +public class Music : ObjectBase { //////////////////////////////////////////////////////////// /// - /// Streamed music played from an audio file + /// Constructs a music from a file + /// + /// This constructor doesn't start playing the music (call + /// to do so). + /// Here is a complete list of all the supported audio formats: + /// ogg, wav, flac, mp3, aiff, au, raw, paf, svx, nist, voc, ircam, + /// w64, mat4, mat5 pvf, htk, sds, avr, sd2, caf, wve, mpc2k, rf64. /// + /// Path of the music file to open //////////////////////////////////////////////////////////// - public class Music : ObjectBase + public Music(string filename) : + base(sfMusic_createFromFile(filename)) { - //////////////////////////////////////////////////////////// - /// - /// Constructs a music from a file - /// - /// This constructor doesn't start playing the music (call - /// to do so). - /// Here is a complete list of all the supported audio formats: - /// ogg, wav, flac, mp3, aiff, au, raw, paf, svx, nist, voc, ircam, - /// w64, mat4, mat5 pvf, htk, sds, avr, sd2, caf, wve, mpc2k, rf64. - /// - /// Path of the music file to open - //////////////////////////////////////////////////////////// - public Music(string filename) : - base(sfMusic_createFromFile(filename)) + if (IsInvalid) { - if (IsInvalid) - { - throw new LoadingFailedException("music", filename); - } + throw new LoadingFailedException("music", filename); } + } - //////////////////////////////////////////////////////////// - /// - /// Constructs a music from a custom stream - /// - /// This constructor doesn't start playing the music (call - /// to do so). - /// Here is a complete list of all the supported audio formats: - /// ogg, wav, flac, mp3, aiff, au, raw, paf, svx, nist, voc, ircam, - /// w64, mat4, mat5 pvf, htk, sds, avr, sd2, caf, wve, mpc2k, rf64. - /// - /// Source stream to read from - //////////////////////////////////////////////////////////// - public Music(Stream stream) : - base(IntPtr.Zero) - { - // Stream needs to stay alive as long as the Music instance is alive - // Disposing of it can only be done in Music's Dispose method - _stream = new StreamAdaptor(stream); - CPointer = sfMusic_createFromStream(_stream.InputStreamPtr); + //////////////////////////////////////////////////////////// + /// + /// Constructs a music from a custom stream + /// + /// This constructor doesn't start playing the music (call + /// to do so). + /// Here is a complete list of all the supported audio formats: + /// ogg, wav, flac, mp3, aiff, au, raw, paf, svx, nist, voc, ircam, + /// w64, mat4, mat5 pvf, htk, sds, avr, sd2, caf, wve, mpc2k, rf64. + /// + /// Source stream to read from + //////////////////////////////////////////////////////////// + public Music(Stream stream) : + base(IntPtr.Zero) + { + // Stream needs to stay alive as long as the Music instance is alive + // Disposing of it can only be done in Music's Dispose method + _stream = new StreamAdaptor(stream); + CPointer = sfMusic_createFromStream(_stream.InputStreamPtr); - if (IsInvalid) - { - throw new LoadingFailedException("music"); - } + if (IsInvalid) + { + throw new LoadingFailedException("music"); } + } - //////////////////////////////////////////////////////////// - /// - /// Constructs a music from an audio file in memory - /// - /// This constructor doesn't start playing the music (call - /// to do so). - /// Here is a complete list of all the supported audio formats: - /// ogg, wav, flac, mp3, aiff, au, raw, paf, svx, nist, voc, ircam, - /// w64, mat4, mat5 pvf, htk, sds, avr, sd2, caf, wve, mpc2k, rf64. - /// - /// Byte array containing the file contents - /// - //////////////////////////////////////////////////////////// - public Music(byte[] bytes) : - base(IntPtr.Zero) - { - // Memory needs to stay pinned as long as the Music instance is alive - // Freeing the handle can only be done in Music's Dispose method - _bytesPin = GCHandle.Alloc(bytes, GCHandleType.Pinned); - CPointer = sfMusic_createFromMemory(_bytesPin.AddrOfPinnedObject(), (UIntPtr)bytes.Length); + //////////////////////////////////////////////////////////// + /// + /// Constructs a music from an audio file in memory + /// + /// This constructor doesn't start playing the music (call + /// to do so). + /// Here is a complete list of all the supported audio formats: + /// ogg, wav, flac, mp3, aiff, au, raw, paf, svx, nist, voc, ircam, + /// w64, mat4, mat5 pvf, htk, sds, avr, sd2, caf, wve, mpc2k, rf64. + /// + /// Byte array containing the file contents + /// + //////////////////////////////////////////////////////////// + public Music(byte[] bytes) : + base(IntPtr.Zero) + { + // Memory needs to stay pinned as long as the Music instance is alive + // Freeing the handle can only be done in Music's Dispose method + _bytesPin = GCHandle.Alloc(bytes, GCHandleType.Pinned); + CPointer = sfMusic_createFromMemory(_bytesPin.AddrOfPinnedObject(), (UIntPtr)bytes.Length); - if (IsInvalid) - { - _bytesPin.Free(); - throw new LoadingFailedException("music"); - } + if (IsInvalid) + { + _bytesPin.Free(); + throw new LoadingFailedException("music"); } + } - //////////////////////////////////////////////////////////// - /// - /// 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 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 stream is played. - /// - //////////////////////////////////////////////////////////// - public void Play() => sfMusic_play(CPointer); + //////////////////////////////////////////////////////////// + /// + /// 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 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 stream is played. + /// + //////////////////////////////////////////////////////////// + public void Play() => sfMusic_play(CPointer); - //////////////////////////////////////////////////////////// - /// - /// Pause the audio stream. - /// - /// This function pauses the stream if it was playing, - /// otherwise (stream already paused or stopped) it has no effect. - /// - //////////////////////////////////////////////////////////// - public void Pause() => sfMusic_pause(CPointer); + //////////////////////////////////////////////////////////// + /// + /// Pause the audio stream. + /// + /// This function pauses the stream if it was playing, + /// otherwise (stream already paused or stopped) it has no effect. + /// + //////////////////////////////////////////////////////////// + public void Pause() => sfMusic_pause(CPointer); - //////////////////////////////////////////////////////////// - /// - /// 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()). - /// - //////////////////////////////////////////////////////////// - public void Stop() => sfMusic_stop(CPointer); + //////////////////////////////////////////////////////////// + /// + /// 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()). + /// + //////////////////////////////////////////////////////////// + public void Stop() => sfMusic_stop(CPointer); - //////////////////////////////////////////////////////////// - /// - /// Sample rate of the music. - /// - /// The sample rate is the number of audio samples played per - /// second. The higher, the better the quality. - /// - //////////////////////////////////////////////////////////// - public uint SampleRate => sfMusic_getSampleRate(CPointer); + //////////////////////////////////////////////////////////// + /// + /// Sample rate of the music. + /// + /// The sample rate is the number of audio samples played per + /// second. The higher, the better the quality. + /// + //////////////////////////////////////////////////////////// + public uint SampleRate => sfMusic_getSampleRate(CPointer); - //////////////////////////////////////////////////////////// - /// - /// 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 spatialisation. - /// - //////////////////////////////////////////////////////////// - public SoundChannel[] ChannelMap + //////////////////////////////////////////////////////////// + /// + /// 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 spatialisation. + /// + //////////////////////////////////////////////////////////// + public SoundChannel[] ChannelMap + { + get { - get + unsafe { - unsafe - { - var channels = sfMusic_getChannelMap(CPointer, out var count); - var arr = new SoundChannel[(int)count]; + var channels = sfMusic_getChannelMap(CPointer, out var count); + var arr = new SoundChannel[(int)count]; - for (var i = 0; i < arr.Length; i++) - { - arr[i] = channels[i]; - } - - return arr; + for (var i = 0; i < arr.Length; i++) + { + arr[i] = channels[i]; } + + return arr; } } + } - //////////////////////////////////////////////////////////// - /// - /// Number of channels (1 = mono, 2 = stereo) - /// - //////////////////////////////////////////////////////////// - public uint ChannelCount => sfMusic_getChannelCount(CPointer); + //////////////////////////////////////////////////////////// + /// + /// Number of channels (1 = mono, 2 = stereo) + /// + //////////////////////////////////////////////////////////// + public uint ChannelCount => sfMusic_getChannelCount(CPointer); - //////////////////////////////////////////////////////////// - /// - /// Current status of the music (see SoundStatus enum) - /// - //////////////////////////////////////////////////////////// - public SoundStatus Status => sfMusic_getStatus(CPointer); + //////////////////////////////////////////////////////////// + /// + /// Current status of the music (see SoundStatus enum) + /// + //////////////////////////////////////////////////////////// + public SoundStatus Status => sfMusic_getStatus(CPointer); - //////////////////////////////////////////////////////////// - /// - /// Total duration of the music - /// - //////////////////////////////////////////////////////////// - public Time Duration => sfMusic_getDuration(CPointer); + //////////////////////////////////////////////////////////// + /// + /// Total duration of the music + /// + //////////////////////////////////////////////////////////// + public Time Duration => sfMusic_getDuration(CPointer); - //////////////////////////////////////////////////////////// - /// - /// Flag if the music should loop after reaching the end. - /// - /// If set, the music will restart from beginning after - /// reaching the end and so on, until it is stopped or - /// IsLooping = false is set. - /// The default looping state for music is false. - /// - //////////////////////////////////////////////////////////// - public bool IsLooping - { - get => sfMusic_isLooping(CPointer); - set => sfMusic_setLooping(CPointer, value); - } + //////////////////////////////////////////////////////////// + /// + /// Flag if the music should loop after reaching the end. + /// + /// If set, the music will restart from beginning after + /// reaching the end and so on, until it is stopped or + /// IsLooping = false is set. + /// The default looping state for music is false. + /// + //////////////////////////////////////////////////////////// + public bool IsLooping + { + get => sfMusic_isLooping(CPointer); + set => sfMusic_setLooping(CPointer, value); + } - //////////////////////////////////////////////////////////// - /// - /// Pitch of the music. - /// - /// 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. - /// - //////////////////////////////////////////////////////////// - public float Pitch - { - get => sfMusic_getPitch(CPointer); - set => sfMusic_setPitch(CPointer, value); - } + //////////////////////////////////////////////////////////// + /// + /// Pitch of the music. + /// + /// 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. + /// + //////////////////////////////////////////////////////////// + public float Pitch + { + get => sfMusic_getPitch(CPointer); + set => sfMusic_setPitch(CPointer, value); + } - //////////////////////////////////////////////////////////// - /// - /// 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. - /// - //////////////////////////////////////////////////////////// - public float Pan - { - get => sfMusic_getPan(CPointer); - set => sfMusic_setPan(CPointer, value); - } + //////////////////////////////////////////////////////////// + /// + /// 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. + /// + //////////////////////////////////////////////////////////// + public float Pan + { + get => sfMusic_getPan(CPointer); + set => sfMusic_setPan(CPointer, value); + } - //////////////////////////////////////////////////////////// - /// - /// Volume of the music. - /// - /// The volume is a value between 0 (mute) and 100 (full volume). - /// The default value for the volume is 100. - /// - //////////////////////////////////////////////////////////// - public float Volume - { - get => sfMusic_getVolume(CPointer); - set => sfMusic_setVolume(CPointer, value); - } + //////////////////////////////////////////////////////////// + /// + /// Volume of the music. + /// + /// The volume is a value between 0 (mute) and 100 (full volume). + /// The default value for the volume is 100. + /// + //////////////////////////////////////////////////////////// + public float Volume + { + get => sfMusic_getVolume(CPointer); + set => sfMusic_setVolume(CPointer, value); + } - //////////////////////////////////////////////////////////// - /// - /// Gets or sets 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. - /// - //////////////////////////////////////////////////////////// - public bool IsSpatializationEnabled - { - get => sfMusic_isSpatializationEnabled(CPointer); - set => sfMusic_setSpatializationEnabled(CPointer, value); - } + //////////////////////////////////////////////////////////// + /// + /// Gets or sets 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. + /// + //////////////////////////////////////////////////////////// + public bool IsSpatializationEnabled + { + get => sfMusic_isSpatializationEnabled(CPointer); + set => sfMusic_setSpatializationEnabled(CPointer, value); + } - //////////////////////////////////////////////////////////// - /// - /// 3D position of the music in the audio scene. - /// - /// Only sounds with one channel (mono sounds) can be - /// spatialized. - /// The default position of a sound is (0, 0, 0). - /// - //////////////////////////////////////////////////////////// - public Vector3f Position - { - get => sfMusic_getPosition(CPointer); - set => sfMusic_setPosition(CPointer, value); - } + //////////////////////////////////////////////////////////// + /// + /// 3D position of the music in the audio scene. + /// + /// Only sounds with one channel (mono sounds) can be + /// spatialized. + /// The default position of a sound is (0, 0, 0). + /// + //////////////////////////////////////////////////////////// + public Vector3f Position + { + get => sfMusic_getPosition(CPointer); + set => sfMusic_setPosition(CPointer, value); + } - //////////////////////////////////////////////////////////// - /// - /// 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). - /// - //////////////////////////////////////////////////////////// - public Vector3f Direction - { - get => sfMusic_getPosition(CPointer); - set => sfMusic_setPosition(CPointer, value); - } + //////////////////////////////////////////////////////////// + /// + /// 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). + /// + //////////////////////////////////////////////////////////// + public Vector3f Direction + { + get => sfMusic_getPosition(CPointer); + set => sfMusic_setPosition(CPointer, value); + } - //////////////////////////////////////////////////////////// - /// - /// 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). - /// - //////////////////////////////////////////////////////////// - public Cone Cone - { - get => new Cone(sfMusic_getCone(CPointer)); - set => sfMusic_setCone(CPointer, value.Marshal()); - } + //////////////////////////////////////////////////////////// + /// + /// 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). + /// + //////////////////////////////////////////////////////////// + public Cone Cone + { + get => new(sfMusic_getCone(CPointer)); + set => sfMusic_setCone(CPointer, value.Marshal()); + } - //////////////////////////////////////////////////////////// - /// - /// 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. - /// - //////////////////////////////////////////////////////////// - public Vector3f Velocity - { - get => sfMusic_getVelocity(CPointer); - set => sfMusic_setVelocity(CPointer, value); - } + //////////////////////////////////////////////////////////// + /// + /// 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. + /// + //////////////////////////////////////////////////////////// + public Vector3f Velocity + { + get => sfMusic_getVelocity(CPointer); + set => sfMusic_setVelocity(CPointer, value); + } - //////////////////////////////////////////////////////////// - /// - /// Doppler factor of the sound - /// - /// The doppler factor determines how strong the doppler - /// shift will be. - /// - //////////////////////////////////////////////////////////// - public float DopplerFactor - { - get => sfMusic_getDopplerFactor(CPointer); - set => sfMusic_setDopplerFactor(CPointer, value); - } + //////////////////////////////////////////////////////////// + /// + /// Doppler factor of the sound + /// + /// The doppler factor determines how strong the doppler + /// shift will be. + /// + //////////////////////////////////////////////////////////// + public float DopplerFactor + { + get => sfMusic_getDopplerFactor(CPointer); + set => sfMusic_setDopplerFactor(CPointer, value); + } - //////////////////////////////////////////////////////////// - /// - /// 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. - /// - //////////////////////////////////////////////////////////// - public float DirectionalAttenuationFactor - { - get => sfMusic_getDirectionalAttenuationFactor(CPointer); - set => sfMusic_setDirectionalAttenuationFactor(CPointer, value); - } + //////////////////////////////////////////////////////////// + /// + /// 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. + /// + //////////////////////////////////////////////////////////// + public float DirectionalAttenuationFactor + { + get => sfMusic_getDirectionalAttenuationFactor(CPointer); + set => sfMusic_setDirectionalAttenuationFactor(CPointer, value); + } - //////////////////////////////////////////////////////////// - /// - /// Make the music'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 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). - /// - //////////////////////////////////////////////////////////// - public bool RelativeToListener - { - get => sfMusic_isRelativeToListener(CPointer); - set => sfMusic_setRelativeToListener(CPointer, value); - } + //////////////////////////////////////////////////////////// + /// + /// Make the music'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 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). + /// + //////////////////////////////////////////////////////////// + public bool RelativeToListener + { + get => sfMusic_isRelativeToListener(CPointer); + set => sfMusic_setRelativeToListener(CPointer, value); + } - //////////////////////////////////////////////////////////// - /// - /// Minimum distance of the music. - /// - /// 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. - /// - //////////////////////////////////////////////////////////// - public float MinDistance - { - get => sfMusic_getMinDistance(CPointer); - set => sfMusic_setMinDistance(CPointer, value); - } + //////////////////////////////////////////////////////////// + /// + /// Minimum distance of the music. + /// + /// 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. + /// + //////////////////////////////////////////////////////////// + public float MinDistance + { + get => sfMusic_getMinDistance(CPointer); + set => sfMusic_setMinDistance(CPointer, value); + } - //////////////////////////////////////////////////////////// - /// - /// 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. - /// - //////////////////////////////////////////////////////////// - public float MaxDistance - { - get => sfMusic_getMaxDistance(CPointer); - set => sfMusic_setMaxDistance(CPointer, value); - } + //////////////////////////////////////////////////////////// + /// + /// 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. + /// + //////////////////////////////////////////////////////////// + public float MaxDistance + { + get => sfMusic_getMaxDistance(CPointer); + set => sfMusic_setMaxDistance(CPointer, value); + } - //////////////////////////////////////////////////////////// - /// - /// 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. - /// - //////////////////////////////////////////////////////////// - public float MinGain - { - get => sfMusic_getMinGain(CPointer); - set => sfMusic_setMinGain(CPointer, value); - } + //////////////////////////////////////////////////////////// + /// + /// 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. + /// + //////////////////////////////////////////////////////////// + public float MinGain + { + get => sfMusic_getMinGain(CPointer); + set => sfMusic_setMinGain(CPointer, value); + } - //////////////////////////////////////////////////////////// - /// - /// 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. - /// - //////////////////////////////////////////////////////////// - public float MaxGain - { - get => sfMusic_getMaxGain(CPointer); - set => sfMusic_setMaxGain(CPointer, value); - } + //////////////////////////////////////////////////////////// + /// + /// 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. + /// + //////////////////////////////////////////////////////////// + public float MaxGain + { + get => sfMusic_getMaxGain(CPointer); + set => sfMusic_setMaxGain(CPointer, value); + } - //////////////////////////////////////////////////////////// - /// - /// Attenuation factor of the music. - /// - /// The attenuation is a multiplicative factor which makes - /// the music 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. - /// - //////////////////////////////////////////////////////////// - public float Attenuation + //////////////////////////////////////////////////////////// + /// + /// Attenuation factor of the music. + /// + /// The attenuation is a multiplicative factor which makes + /// the music 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. + /// + //////////////////////////////////////////////////////////// + public float Attenuation + { + get => sfMusic_getAttenuation(CPointer); + set => sfMusic_setAttenuation(CPointer, value); + } + + //////////////////////////////////////////////////////////// + /// + /// Current playing position of the music. + /// + /// The playing position can be changed when the music is + /// either paused or playing. + /// + //////////////////////////////////////////////////////////// + public Time PlayingOffset + { + get => sfMusic_getPlayingOffset(CPointer); + set => sfMusic_setPlayingOffset(CPointer, value); + } + + //////////////////////////////////////////////////////////// + /// + /// Current loop points of the music. + /// + /// Since setting performs some adjustments on the + /// provided values and rounds them to internal samples, getting this + /// value later is not guaranteed to return the same times passed + /// into it. However, it is guaranteed to return times that will map + /// to the valid internal samples of this Music if they are later + /// set again. + /// + //////////////////////////////////////////////////////////// + public TimeSpan LoopPoints + { + get => sfMusic_getLoopPoints(CPointer); + set => sfMusic_setLoopPoints(CPointer, value); + } + + //////////////////////////////////////////////////////////// + /// + /// 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. + /// + /// The effect processor to attach to this sound, attach a null processor to disable processing + //////////////////////////////////////////////////////////// + public void SetEffectProcessor(EffectProcessor effectProcessor) + { + _effectProcessor = (inputFrames, inputFrameCount, outputFrames, outputFrameCount, frameChannelCount) => { - get => sfMusic_getAttenuation(CPointer); - set => sfMusic_setAttenuation(CPointer, value); - } + var inputFramesArray = new float[inputFrameCount]; + var outputFramesArray = new float[outputFrameCount]; - //////////////////////////////////////////////////////////// - /// - /// Current playing position of the music. - /// - /// The playing position can be changed when the music is - /// either paused or playing. - /// - //////////////////////////////////////////////////////////// - public Time PlayingOffset + Marshal.Copy(inputFrames, inputFramesArray, 0, inputFramesArray.Length); + var written = effectProcessor(inputFramesArray, outputFramesArray, frameChannelCount); + Marshal.Copy(outputFramesArray, 0, outputFrames, outputFramesArray.Length); + + return written; + }; + + sfMusic_setEffectProcessor(CPointer, Marshal.GetFunctionPointerForDelegate(_effectProcessor)); + } + + //////////////////////////////////////////////////////////// + /// + /// Provide a string describing the object + /// + /// String description of the object + //////////////////////////////////////////////////////////// + public override string ToString() + { + if (IsInvalid) { - get => sfMusic_getPlayingOffset(CPointer); - set => sfMusic_setPlayingOffset(CPointer, value); + return MakeDisposedObjectString(); } - //////////////////////////////////////////////////////////// - /// - /// Current loop points of the music. - /// - /// Since setting performs some adjustments on the - /// provided values and rounds them to internal samples, getting this - /// value later is not guaranteed to return the same times passed - /// into it. However, it is guaranteed to return times that will map - /// to the valid internal samples of this Music if they are later - /// set again. - /// - //////////////////////////////////////////////////////////// - public TimeSpan LoopPoints + return "[Music]" + + " SampleRate(" + SampleRate + ")" + + " ChannelCount(" + ChannelCount + ")" + + " Status(" + Status + ")" + + " Duration(" + Duration + ")" + + " IsLooping(" + IsLooping + ")" + + " Pitch(" + Pitch + ")" + + " Volume(" + Volume + ")" + + " Position(" + Position + ")" + + " RelativeToListener(" + RelativeToListener + ")" + + " MinDistance(" + MinDistance + ")" + + " Attenuation(" + Attenuation + ")" + + " PlayingOffset(" + PlayingOffset + ")" + + " LoopPoints(" + LoopPoints + ")"; + } + + //////////////////////////////////////////////////////////// + /// + /// Handle the destruction of the object + /// + /// Is the GC disposing the object, or is it an explicit call ? + //////////////////////////////////////////////////////////// + protected override void Destroy(bool disposing) + { + if (disposing) { - get => sfMusic_getLoopPoints(CPointer); - set => sfMusic_setLoopPoints(CPointer, value); + _stream?.Dispose(); } - //////////////////////////////////////////////////////////// - /// - /// 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. - /// - /// The effect processor to attach to this sound, attach a null processor to disable processing - //////////////////////////////////////////////////////////// - public void SetEffectProcessor(EffectProcessor effectProcessor) + if (_bytesPin.IsAllocated) { - _effectProcessor = (inputFrames, inputFrameCount, outputFrames, outputFrameCount, frameChannelCount) => - { - var inputFramesArray = new float[inputFrameCount]; - var outputFramesArray = new float[outputFrameCount]; - - Marshal.Copy(inputFrames, inputFramesArray, 0, inputFramesArray.Length); - var written = effectProcessor(inputFramesArray, outputFramesArray, frameChannelCount); - Marshal.Copy(outputFramesArray, 0, outputFrames, outputFramesArray.Length); + _bytesPin.Free(); + } - return written; - }; + sfMusic_destroy(CPointer); + } - sfMusic_setEffectProcessor(CPointer, Marshal.GetFunctionPointerForDelegate(_effectProcessor)); - } + private readonly StreamAdaptor _stream; + private GCHandle _bytesPin; + private EffectProcessorInternal _effectProcessor; - //////////////////////////////////////////////////////////// + /// + /// Structure defining a Time range. + /// + [StructLayout(LayoutKind.Sequential)] + public struct TimeSpan + { /// - /// Provide a string describing the object + /// Constructs TimeSpan from offset and a length /// - /// String description of the object - //////////////////////////////////////////////////////////// - public override string ToString() + /// beginning offset of the time range + /// length of the time range + public TimeSpan(Time offset, Time length) { - if (IsInvalid) - { - return MakeDisposedObjectString(); - } - - return "[Music]" + - " SampleRate(" + SampleRate + ")" + - " ChannelCount(" + ChannelCount + ")" + - " Status(" + Status + ")" + - " Duration(" + Duration + ")" + - " IsLooping(" + IsLooping + ")" + - " Pitch(" + Pitch + ")" + - " Volume(" + Volume + ")" + - " Position(" + Position + ")" + - " RelativeToListener(" + RelativeToListener + ")" + - " MinDistance(" + MinDistance + ")" + - " Attenuation(" + Attenuation + ")" + - " PlayingOffset(" + PlayingOffset + ")" + - " LoopPoints(" + LoopPoints + ")"; + Offset = offset; + Length = length; } - //////////////////////////////////////////////////////////// /// - /// Handle the destruction of the object + /// The beginning of the time range /// - /// Is the GC disposing the object, or is it an explicit call ? - //////////////////////////////////////////////////////////// - protected override void Destroy(bool disposing) - { - if (disposing) - { - _stream?.Dispose(); - } - - if (_bytesPin.IsAllocated) - { - _bytesPin.Free(); - } - - sfMusic_destroy(CPointer); - } - - private readonly StreamAdaptor _stream; - private GCHandle _bytesPin; - private EffectProcessorInternal _effectProcessor; + public Time Offset; /// - /// Structure defining a Time range. + /// The length of the time range /// - [StructLayout(LayoutKind.Sequential)] - public struct TimeSpan - { - /// - /// Constructs TimeSpan from offset and a length - /// - /// beginning offset of the time range - /// length of the time range - public TimeSpan(Time offset, Time length) - { - Offset = offset; - Length = length; - } - - /// - /// The beginning of the time range - /// - public Time Offset; - - /// - /// The length of the time range - /// - public Time Length; - } + public Time Length; + } - #region Imports - [DllImport(CSFML.Audio, CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] - private static extern IntPtr sfMusic_createFromFile(string filename); + #region Imports + [DllImport(CSFML.Audio, CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] + private static extern IntPtr sfMusic_createFromFile(string filename); - [DllImport(CSFML.Audio, CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] - private static extern unsafe IntPtr sfMusic_createFromStream(IntPtr stream); + [DllImport(CSFML.Audio, CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] + private static extern unsafe IntPtr sfMusic_createFromStream(IntPtr stream); - [DllImport(CSFML.Audio, CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] - private static extern IntPtr sfMusic_createFromMemory(IntPtr data, UIntPtr size); + [DllImport(CSFML.Audio, CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] + private static extern IntPtr sfMusic_createFromMemory(IntPtr data, UIntPtr size); - [DllImport(CSFML.Audio, CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] - private static extern void sfMusic_destroy(IntPtr musicStream); + [DllImport(CSFML.Audio, CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] + private static extern void sfMusic_destroy(IntPtr musicStream); - [DllImport(CSFML.Audio, CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] - private static extern void sfMusic_play(IntPtr music); + [DllImport(CSFML.Audio, CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] + private static extern void sfMusic_play(IntPtr music); - [DllImport(CSFML.Audio, CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] - private static extern void sfMusic_pause(IntPtr music); + [DllImport(CSFML.Audio, CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] + private static extern void sfMusic_pause(IntPtr music); - [DllImport(CSFML.Audio, CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] - private static extern void sfMusic_stop(IntPtr music); + [DllImport(CSFML.Audio, CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] + private static extern void sfMusic_stop(IntPtr music); - [DllImport(CSFML.Audio, CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] - private static extern unsafe SoundChannel* sfMusic_getChannelMap(IntPtr music, out UIntPtr count); + [DllImport(CSFML.Audio, CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] + private static extern unsafe SoundChannel* sfMusic_getChannelMap(IntPtr music, out UIntPtr count); - [DllImport(CSFML.Audio, CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] - private static extern SoundStatus sfMusic_getStatus(IntPtr music); + [DllImport(CSFML.Audio, CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] + private static extern SoundStatus sfMusic_getStatus(IntPtr music); - [DllImport(CSFML.Audio, CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] - private static extern Time sfMusic_getPlayingOffset(IntPtr music); + [DllImport(CSFML.Audio, CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] + private static extern Time sfMusic_getPlayingOffset(IntPtr music); - [DllImport(CSFML.Audio, CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] - private static extern Time sfMusic_getDuration(IntPtr music); + [DllImport(CSFML.Audio, CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] + private static extern Time sfMusic_getDuration(IntPtr music); - [DllImport(CSFML.Audio, CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] - private static extern TimeSpan sfMusic_getLoopPoints(IntPtr music); + [DllImport(CSFML.Audio, CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] + private static extern TimeSpan sfMusic_getLoopPoints(IntPtr music); - [DllImport(CSFML.Audio, CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] - private static extern void sfMusic_setLoopPoints(IntPtr music, TimeSpan timePoints); + [DllImport(CSFML.Audio, CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] + private static extern void sfMusic_setLoopPoints(IntPtr music, TimeSpan timePoints); - [DllImport(CSFML.Audio, CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] - private static extern uint sfMusic_getChannelCount(IntPtr music); + [DllImport(CSFML.Audio, CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] + private static extern uint sfMusic_getChannelCount(IntPtr music); - [DllImport(CSFML.Audio, CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] - private static extern uint sfMusic_getSampleRate(IntPtr music); + [DllImport(CSFML.Audio, CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] + private static extern uint sfMusic_getSampleRate(IntPtr music); - [DllImport(CSFML.Audio, CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] - private static extern void sfMusic_setPitch(IntPtr music, float pitch); + [DllImport(CSFML.Audio, CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] + private static extern void sfMusic_setPitch(IntPtr music, float pitch); - [DllImport(CSFML.Audio, CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] - private static extern void sfMusic_setPan(IntPtr music, float pan); + [DllImport(CSFML.Audio, CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] + private static extern void sfMusic_setPan(IntPtr music, float pan); - [DllImport(CSFML.Audio, CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] - private static extern void sfMusic_setLooping(IntPtr music, bool loop); + [DllImport(CSFML.Audio, CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] + private static extern void sfMusic_setLooping(IntPtr music, bool loop); - [DllImport(CSFML.Audio, CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] - private static extern void sfMusic_setVolume(IntPtr music, float volume); + [DllImport(CSFML.Audio, CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] + private static extern void sfMusic_setVolume(IntPtr music, float volume); - [DllImport(CSFML.Audio, CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] - private static extern void sfMusic_setSpatializationEnabled(IntPtr music, bool enabled); + [DllImport(CSFML.Audio, CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] + private static extern void sfMusic_setSpatializationEnabled(IntPtr music, bool enabled); - [DllImport(CSFML.Audio, CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] - private static extern void sfMusic_setPosition(IntPtr music, Vector3f position); + [DllImport(CSFML.Audio, CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] + private static extern void sfMusic_setPosition(IntPtr music, Vector3f position); - [DllImport(CSFML.Audio, CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] - private static extern void sfMusic_setDirection(IntPtr music, Vector3f direction); + [DllImport(CSFML.Audio, CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] + private static extern void sfMusic_setDirection(IntPtr music, Vector3f direction); - [DllImport(CSFML.Audio, CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] - private static extern void sfMusic_setCone(IntPtr music, Cone.MarshalData cone); + [DllImport(CSFML.Audio, CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] + private static extern void sfMusic_setCone(IntPtr music, Cone.MarshalData cone); - [DllImport(CSFML.Audio, CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] - private static extern void sfMusic_setVelocity(IntPtr music, Vector3f velocity); + [DllImport(CSFML.Audio, CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] + private static extern void sfMusic_setVelocity(IntPtr music, Vector3f velocity); - [DllImport(CSFML.Audio, CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] - private static extern void sfMusic_setDopplerFactor(IntPtr music, float factor); + [DllImport(CSFML.Audio, CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] + private static extern void sfMusic_setDopplerFactor(IntPtr music, float factor); - [DllImport(CSFML.Audio, CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] - private static extern void sfMusic_setDirectionalAttenuationFactor(IntPtr music, float factor); + [DllImport(CSFML.Audio, CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] + private static extern void sfMusic_setDirectionalAttenuationFactor(IntPtr music, float factor); - [DllImport(CSFML.Audio, CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] - private static extern void sfMusic_setRelativeToListener(IntPtr music, bool relative); + [DllImport(CSFML.Audio, CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] + private static extern void sfMusic_setRelativeToListener(IntPtr music, bool relative); - [DllImport(CSFML.Audio, CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] - private static extern void sfMusic_setMinDistance(IntPtr music, float minDistance); + [DllImport(CSFML.Audio, CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] + private static extern void sfMusic_setMinDistance(IntPtr music, float minDistance); - [DllImport(CSFML.Audio, CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] - private static extern void sfMusic_setMaxDistance(IntPtr music, float maxDistance); + [DllImport(CSFML.Audio, CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] + private static extern void sfMusic_setMaxDistance(IntPtr music, float maxDistance); - [DllImport(CSFML.Audio, CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] - private static extern void sfMusic_setMinGain(IntPtr music, float gain); + [DllImport(CSFML.Audio, CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] + private static extern void sfMusic_setMinGain(IntPtr music, float gain); - [DllImport(CSFML.Audio, CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] - private static extern void sfMusic_setMaxGain(IntPtr music, float gain); + [DllImport(CSFML.Audio, CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] + private static extern void sfMusic_setMaxGain(IntPtr music, float gain); - [DllImport(CSFML.Audio, CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] - private static extern void sfMusic_setAttenuation(IntPtr music, float attenuation); + [DllImport(CSFML.Audio, CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] + private static extern void sfMusic_setAttenuation(IntPtr music, float attenuation); - [DllImport(CSFML.Audio, CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] - private static extern void sfMusic_setPlayingOffset(IntPtr music, Time timeOffset); + [DllImport(CSFML.Audio, CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] + private static extern void sfMusic_setPlayingOffset(IntPtr music, Time timeOffset); - [DllImport(CSFML.Audio, CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] - [return: MarshalAs(UnmanagedType.I1)] - private static extern bool sfMusic_isLooping(IntPtr music); + [DllImport(CSFML.Audio, CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] + [return: MarshalAs(UnmanagedType.I1)] + private static extern bool sfMusic_isLooping(IntPtr music); - [DllImport(CSFML.Audio, CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] - private static extern void sfMusic_setEffectProcessor(IntPtr music, IntPtr effectProcessor); + [DllImport(CSFML.Audio, CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] + private static extern void sfMusic_setEffectProcessor(IntPtr music, IntPtr effectProcessor); - [DllImport(CSFML.Audio, CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] - private static extern float sfMusic_getPitch(IntPtr music); + [DllImport(CSFML.Audio, CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] + private static extern float sfMusic_getPitch(IntPtr music); - [DllImport(CSFML.Audio, CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] - private static extern float sfMusic_getPan(IntPtr music); + [DllImport(CSFML.Audio, CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] + private static extern float sfMusic_getPan(IntPtr music); - [DllImport(CSFML.Audio, CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] - [return: MarshalAs(UnmanagedType.I1)] - private static extern bool sfMusic_isSpatializationEnabled(IntPtr music); + [DllImport(CSFML.Audio, CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] + [return: MarshalAs(UnmanagedType.I1)] + private static extern bool sfMusic_isSpatializationEnabled(IntPtr music); - [DllImport(CSFML.Audio, CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] - private static extern float sfMusic_getVolume(IntPtr music); + [DllImport(CSFML.Audio, CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] + private static extern float sfMusic_getVolume(IntPtr music); - [DllImport(CSFML.Audio, CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] - private static extern Vector3f sfMusic_getPosition(IntPtr music); + [DllImport(CSFML.Audio, CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] + private static extern Vector3f sfMusic_getPosition(IntPtr music); - [DllImport(CSFML.Audio, CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] - private static extern Vector3f sfMusic_getDirection(IntPtr music); + [DllImport(CSFML.Audio, CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] + private static extern Vector3f sfMusic_getDirection(IntPtr music); - [DllImport(CSFML.Audio, CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] - private static extern Cone.MarshalData sfMusic_getCone(IntPtr music); + [DllImport(CSFML.Audio, CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] + private static extern Cone.MarshalData sfMusic_getCone(IntPtr music); - [DllImport(CSFML.Audio, CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] - private static extern Vector3f sfMusic_getVelocity(IntPtr music); + [DllImport(CSFML.Audio, CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] + private static extern Vector3f sfMusic_getVelocity(IntPtr music); - [DllImport(CSFML.Audio, CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] - private static extern float sfMusic_getDopplerFactor(IntPtr music); + [DllImport(CSFML.Audio, CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] + private static extern float sfMusic_getDopplerFactor(IntPtr music); - [DllImport(CSFML.Audio, CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] - private static extern float sfMusic_getDirectionalAttenuationFactor(IntPtr music); + [DllImport(CSFML.Audio, CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] + private static extern float sfMusic_getDirectionalAttenuationFactor(IntPtr music); - [DllImport(CSFML.Audio, CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] - [return: MarshalAs(UnmanagedType.I1)] - private static extern bool sfMusic_isRelativeToListener(IntPtr music); + [DllImport(CSFML.Audio, CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] + [return: MarshalAs(UnmanagedType.I1)] + private static extern bool sfMusic_isRelativeToListener(IntPtr music); - [DllImport(CSFML.Audio, CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] - private static extern float sfMusic_getMinDistance(IntPtr music); + [DllImport(CSFML.Audio, CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] + private static extern float sfMusic_getMinDistance(IntPtr music); - [DllImport(CSFML.Audio, CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] - private static extern float sfMusic_getMaxDistance(IntPtr music); + [DllImport(CSFML.Audio, CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] + private static extern float sfMusic_getMaxDistance(IntPtr music); - [DllImport(CSFML.Audio, CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] - private static extern float sfMusic_getMinGain(IntPtr music); + [DllImport(CSFML.Audio, CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] + private static extern float sfMusic_getMinGain(IntPtr music); - [DllImport(CSFML.Audio, CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] - private static extern float sfMusic_getMaxGain(IntPtr music); + [DllImport(CSFML.Audio, CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] + private static extern float sfMusic_getMaxGain(IntPtr music); - [DllImport(CSFML.Audio, CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] - private static extern float sfMusic_getAttenuation(IntPtr music); - #endregion - } + [DllImport(CSFML.Audio, CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] + private static extern float sfMusic_getAttenuation(IntPtr music); + #endregion } diff --git a/src/SFML.Audio/Sound.cs b/src/SFML.Audio/Sound.cs index 852374d6..7426555f 100644 --- a/src/SFML.Audio/Sound.cs +++ b/src/SFML.Audio/Sound.cs @@ -3,596 +3,595 @@ using System.Security; using SFML.System; -namespace SFML.Audio +namespace SFML.Audio; + +//////////////////////////////////////////////////////////// +/// +/// Enumeration of all possible sound states +/// +//////////////////////////////////////////////////////////// +public enum SoundStatus +{ + /// Sound is not playing + Stopped, + + /// Sound is paused + Paused, + + /// Sound is playing + Playing +} + +//////////////////////////////////////////////////////////// +/// +/// Regular sound that can be played in the audio environment +/// +//////////////////////////////////////////////////////////// +public class Sound : ObjectBase { //////////////////////////////////////////////////////////// /// - /// Enumeration of all possible sound states + /// Construct the sound with a buffer /// + /// Sound buffer containing the audio data to play with the sound //////////////////////////////////////////////////////////// - public enum SoundStatus - { - /// Sound is not playing - Stopped, + public Sound(SoundBuffer buffer) : + base(sfSound_create(buffer.CPointer)) => SoundBuffer = buffer; - /// Sound is paused - Paused, + //////////////////////////////////////////////////////////// + /// + /// Construct the sound from another source + /// + /// Sound to copy + //////////////////////////////////////////////////////////// + public Sound(Sound copy) : + base(sfSound_copy(copy.CPointer)) => SoundBuffer = copy.SoundBuffer; - /// Sound is playing - Playing - } + //////////////////////////////////////////////////////////// + /// + /// 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. + /// + //////////////////////////////////////////////////////////// + public void Play() => sfSound_play(CPointer); + + //////////////////////////////////////////////////////////// + /// + /// Pause the sound. + /// + /// This function pauses the sound if it was playing, + /// otherwise (sound already paused or stopped) it has no effect. + /// + //////////////////////////////////////////////////////////// + public void Pause() => sfSound_pause(CPointer); + + //////////////////////////////////////////////////////////// + /// + /// 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()). + /// + //////////////////////////////////////////////////////////// + public void Stop() => sfSound_stop(CPointer); //////////////////////////////////////////////////////////// /// - /// Regular sound that can be played in the audio environment + /// Buffer containing the sound data to play through the sound. + /// + /// It is important to note that the sound buffer is not copied, + /// thus the SoundBuffer instance must remain alive as long + /// as it is attached to the sound. /// //////////////////////////////////////////////////////////// - public class Sound : ObjectBase + public SoundBuffer SoundBuffer { - //////////////////////////////////////////////////////////// - /// - /// Construct the sound with a buffer - /// - /// Sound buffer containing the audio data to play with the sound - //////////////////////////////////////////////////////////// - public Sound(SoundBuffer buffer) : - base(sfSound_create(buffer.CPointer)) => SoundBuffer = buffer; - - //////////////////////////////////////////////////////////// - /// - /// Construct the sound from another source - /// - /// Sound to copy - //////////////////////////////////////////////////////////// - public Sound(Sound copy) : - base(sfSound_copy(copy.CPointer)) => SoundBuffer = copy.SoundBuffer; - - //////////////////////////////////////////////////////////// - /// - /// 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. - /// - //////////////////////////////////////////////////////////// - public void Play() => sfSound_play(CPointer); - - //////////////////////////////////////////////////////////// - /// - /// Pause the sound. - /// - /// This function pauses the sound if it was playing, - /// otherwise (sound already paused or stopped) it has no effect. - /// - //////////////////////////////////////////////////////////// - public void Pause() => sfSound_pause(CPointer); - - //////////////////////////////////////////////////////////// - /// - /// 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()). - /// - //////////////////////////////////////////////////////////// - public void Stop() => sfSound_stop(CPointer); - - //////////////////////////////////////////////////////////// - /// - /// Buffer containing the sound data to play through the sound. - /// - /// It is important to note that the sound buffer is not copied, - /// thus the SoundBuffer instance must remain alive as long - /// as it is attached to the sound. - /// - //////////////////////////////////////////////////////////// - public SoundBuffer SoundBuffer - { - get => _buffer; - set { _buffer = value; sfSound_setBuffer(CPointer, value != null ? value.CPointer : IntPtr.Zero); } - } + get => _buffer; + set { _buffer = value; sfSound_setBuffer(CPointer, value?.CPointer ?? IntPtr.Zero); } + } - //////////////////////////////////////////////////////////// - /// - /// Current status of the sound (see SoundStatus enum) - /// - //////////////////////////////////////////////////////////// - public SoundStatus Status => sfSound_getStatus(CPointer); - - //////////////////////////////////////////////////////////// - /// - /// Flag if 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 - /// IsLooping = false is set. - /// The default looping state for sounds is false. - /// - //////////////////////////////////////////////////////////// - public bool IsLooping - { - get => sfSound_isLooping(CPointer); - set => sfSound_setLooping(CPointer, value); - } + //////////////////////////////////////////////////////////// + /// + /// Current status of the sound (see SoundStatus enum) + /// + //////////////////////////////////////////////////////////// + public SoundStatus Status => sfSound_getStatus(CPointer); - //////////////////////////////////////////////////////////// - /// - /// 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. - /// - //////////////////////////////////////////////////////////// - public float Pitch - { - get => sfSound_getPitch(CPointer); - set => sfSound_setPitch(CPointer, value); - } + //////////////////////////////////////////////////////////// + /// + /// Flag if 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 + /// IsLooping = false is set. + /// The default looping state for sounds is false. + /// + //////////////////////////////////////////////////////////// + public bool IsLooping + { + get => sfSound_isLooping(CPointer); + set => sfSound_setLooping(CPointer, value); + } - //////////////////////////////////////////////////////////// - /// - /// 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. - /// - //////////////////////////////////////////////////////////// - public float Pan - { - get => sfSound_getPan(CPointer); - set => sfSound_setPan(CPointer, value); - } + //////////////////////////////////////////////////////////// + /// + /// 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. + /// + //////////////////////////////////////////////////////////// + public float Pitch + { + get => sfSound_getPitch(CPointer); + set => sfSound_setPitch(CPointer, value); + } - //////////////////////////////////////////////////////////// - /// - /// Volume of the sound. - /// - /// The volume is a value between 0 (mute) and 100 (full volume). - /// The default value for the volume is 100. - /// - //////////////////////////////////////////////////////////// - public float Volume - { - get => sfSound_getVolume(CPointer); - set => sfSound_setVolume(CPointer, value); - } + //////////////////////////////////////////////////////////// + /// + /// 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. + /// + //////////////////////////////////////////////////////////// + public float Pan + { + get => sfSound_getPan(CPointer); + set => sfSound_setPan(CPointer, value); + } - //////////////////////////////////////////////////////////// - /// - /// Gets or sets 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. - /// - //////////////////////////////////////////////////////////// - public bool IsSpatializationEnabled - { - get => sfSound_isSpatializationEnabled(CPointer); - set => sfSound_setSpatializationEnabled(CPointer, value); - } + //////////////////////////////////////////////////////////// + /// + /// Volume of the sound. + /// + /// The volume is a value between 0 (mute) and 100 (full volume). + /// The default value for the volume is 100. + /// + //////////////////////////////////////////////////////////// + public float Volume + { + get => sfSound_getVolume(CPointer); + set => sfSound_setVolume(CPointer, value); + } - //////////////////////////////////////////////////////////// - /// - /// Current playing position of the sound. - /// - /// The playing position can be changed when the sound is - /// either paused or playing. - /// - //////////////////////////////////////////////////////////// - public Time PlayingOffset - { - get => sfSound_getPlayingOffset(CPointer); - set => sfSound_setPlayingOffset(CPointer, value); - } + //////////////////////////////////////////////////////////// + /// + /// Gets or sets 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. + /// + //////////////////////////////////////////////////////////// + public bool IsSpatializationEnabled + { + get => sfSound_isSpatializationEnabled(CPointer); + set => sfSound_setSpatializationEnabled(CPointer, value); + } - //////////////////////////////////////////////////////////// - /// - /// 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). - /// - //////////////////////////////////////////////////////////// - public Vector3f Position - { - get => sfSound_getPosition(CPointer); - set => sfSound_setPosition(CPointer, value); - } + //////////////////////////////////////////////////////////// + /// + /// Current playing position of the sound. + /// + /// The playing position can be changed when the sound is + /// either paused or playing. + /// + //////////////////////////////////////////////////////////// + public Time PlayingOffset + { + get => sfSound_getPlayingOffset(CPointer); + set => sfSound_setPlayingOffset(CPointer, value); + } - //////////////////////////////////////////////////////////// - /// - /// 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). - /// - //////////////////////////////////////////////////////////// - public Vector3f Direction - { - get => sfSound_getPosition(CPointer); - set => sfSound_setPosition(CPointer, value); - } + //////////////////////////////////////////////////////////// + /// + /// 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). + /// + //////////////////////////////////////////////////////////// + public Vector3f Position + { + get => sfSound_getPosition(CPointer); + set => sfSound_setPosition(CPointer, value); + } - //////////////////////////////////////////////////////////// - /// - /// 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). - /// - //////////////////////////////////////////////////////////// - public Cone Cone - { - get => new Cone(sfSound_getCone(CPointer)); - set => sfSound_setCone(CPointer, value.Marshal()); - } + //////////////////////////////////////////////////////////// + /// + /// 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). + /// + //////////////////////////////////////////////////////////// + public Vector3f Direction + { + get => sfSound_getPosition(CPointer); + set => sfSound_setPosition(CPointer, value); + } - //////////////////////////////////////////////////////////// - /// - /// 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. - /// - //////////////////////////////////////////////////////////// - public Vector3f Velocity - { - get => sfSound_getVelocity(CPointer); - set => sfSound_setVelocity(CPointer, value); - } + //////////////////////////////////////////////////////////// + /// + /// 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). + /// + //////////////////////////////////////////////////////////// + public Cone Cone + { + get => new(sfSound_getCone(CPointer)); + set => sfSound_setCone(CPointer, value.Marshal()); + } - //////////////////////////////////////////////////////////// - /// - /// Doppler factor of the sound - /// - /// The doppler factor determines how strong the doppler - /// shift will be. - /// - //////////////////////////////////////////////////////////// - public float DopplerFactor - { - get => sfSound_getDopplerFactor(CPointer); - set => sfSound_setDopplerFactor(CPointer, value); - } + //////////////////////////////////////////////////////////// + /// + /// 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. + /// + //////////////////////////////////////////////////////////// + public Vector3f Velocity + { + get => sfSound_getVelocity(CPointer); + set => sfSound_setVelocity(CPointer, value); + } - //////////////////////////////////////////////////////////// - /// - /// 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. - /// - //////////////////////////////////////////////////////////// - public float DirectionalAttenuationFactor - { - get => sfSound_getDirectionalAttenuationFactor(CPointer); - set => sfSound_setDirectionalAttenuationFactor(CPointer, value); - } + //////////////////////////////////////////////////////////// + /// + /// Doppler factor of the sound + /// + /// The doppler factor determines how strong the doppler + /// shift will be. + /// + //////////////////////////////////////////////////////////// + public float DopplerFactor + { + get => sfSound_getDopplerFactor(CPointer); + set => sfSound_setDopplerFactor(CPointer, value); + } - //////////////////////////////////////////////////////////// - /// - /// Make the music'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 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). - /// - //////////////////////////////////////////////////////////// - public bool RelativeToListener - { - get => sfSound_isRelativeToListener(CPointer); - set => sfSound_setRelativeToListener(CPointer, value); - } + //////////////////////////////////////////////////////////// + /// + /// 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. + /// + //////////////////////////////////////////////////////////// + public float DirectionalAttenuationFactor + { + get => sfSound_getDirectionalAttenuationFactor(CPointer); + set => sfSound_setDirectionalAttenuationFactor(CPointer, value); + } - //////////////////////////////////////////////////////////// - /// - /// 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. - /// - //////////////////////////////////////////////////////////// - public float MinDistance - { - get => sfSound_getMinDistance(CPointer); - set => sfSound_setMinDistance(CPointer, value); - } + //////////////////////////////////////////////////////////// + /// + /// Make the music'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 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). + /// + //////////////////////////////////////////////////////////// + public bool RelativeToListener + { + get => sfSound_isRelativeToListener(CPointer); + set => sfSound_setRelativeToListener(CPointer, value); + } - //////////////////////////////////////////////////////////// - /// - /// 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. - /// - //////////////////////////////////////////////////////////// - public float MaxDistance - { - get => sfSound_getMaxDistance(CPointer); - set => sfSound_setMaxDistance(CPointer, value); - } + //////////////////////////////////////////////////////////// + /// + /// 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. + /// + //////////////////////////////////////////////////////////// + public float MinDistance + { + get => sfSound_getMinDistance(CPointer); + set => sfSound_setMinDistance(CPointer, value); + } - //////////////////////////////////////////////////////////// - /// - /// 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. - /// - //////////////////////////////////////////////////////////// - public float MinGain - { - get => sfSound_getMinGain(CPointer); - set => sfSound_setMinGain(CPointer, value); - } + //////////////////////////////////////////////////////////// + /// + /// 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. + /// + //////////////////////////////////////////////////////////// + public float MaxDistance + { + get => sfSound_getMaxDistance(CPointer); + set => sfSound_setMaxDistance(CPointer, value); + } - //////////////////////////////////////////////////////////// - /// - /// 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. - /// - //////////////////////////////////////////////////////////// - public float MaxGain - { - get => sfSound_getMaxGain(CPointer); - set => sfSound_setMaxGain(CPointer, value); - } + //////////////////////////////////////////////////////////// + /// + /// 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. + /// + //////////////////////////////////////////////////////////// + public float MinGain + { + get => sfSound_getMinGain(CPointer); + set => sfSound_setMinGain(CPointer, value); + } - //////////////////////////////////////////////////////////// - /// - /// Attenuation factor of the music. - /// - /// The attenuation is a multiplicative factor which makes - /// the music 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. - /// - //////////////////////////////////////////////////////////// - public float Attenuation - { - get => sfSound_getAttenuation(CPointer); - set => sfSound_setAttenuation(CPointer, value); - } + //////////////////////////////////////////////////////////// + /// + /// 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. + /// + //////////////////////////////////////////////////////////// + public float MaxGain + { + get => sfSound_getMaxGain(CPointer); + set => sfSound_setMaxGain(CPointer, value); + } - //////////////////////////////////////////////////////////// - /// - /// 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. - /// - /// The effect processor to attach to this sound, attach a null processor to disable processing - //////////////////////////////////////////////////////////// - public void SetEffectProcessor(EffectProcessor effectProcessor) + //////////////////////////////////////////////////////////// + /// + /// Attenuation factor of the music. + /// + /// The attenuation is a multiplicative factor which makes + /// the music 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. + /// + //////////////////////////////////////////////////////////// + public float Attenuation + { + get => sfSound_getAttenuation(CPointer); + set => sfSound_setAttenuation(CPointer, value); + } + + //////////////////////////////////////////////////////////// + /// + /// 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. + /// + /// The effect processor to attach to this sound, attach a null processor to disable processing + //////////////////////////////////////////////////////////// + public void SetEffectProcessor(EffectProcessor effectProcessor) + { + _effectProcessor = (inputFrames, inputFrameCount, outputFrames, outputFrameCount, frameChannelCount) => { - _effectProcessor = (inputFrames, inputFrameCount, outputFrames, outputFrameCount, frameChannelCount) => - { - var inputFramesArray = new float[inputFrameCount]; - var outputFramesArray = new float[outputFrameCount]; + var inputFramesArray = new float[inputFrameCount]; + var outputFramesArray = new float[outputFrameCount]; - Marshal.Copy(inputFrames, inputFramesArray, 0, inputFramesArray.Length); - var written = effectProcessor(inputFramesArray, outputFramesArray, frameChannelCount); - Marshal.Copy(outputFramesArray, 0, outputFrames, outputFramesArray.Length); + Marshal.Copy(inputFrames, inputFramesArray, 0, inputFramesArray.Length); + var written = effectProcessor(inputFramesArray, outputFramesArray, frameChannelCount); + Marshal.Copy(outputFramesArray, 0, outputFrames, outputFramesArray.Length); - return written; - }; + return written; + }; - sfSound_setEffectProcessor(CPointer, Marshal.GetFunctionPointerForDelegate(_effectProcessor)); - } + sfSound_setEffectProcessor(CPointer, Marshal.GetFunctionPointerForDelegate(_effectProcessor)); + } - //////////////////////////////////////////////////////////// - /// - /// Provide a string describing the object - /// - /// String description of the object - //////////////////////////////////////////////////////////// - public override string ToString() + //////////////////////////////////////////////////////////// + /// + /// Provide a string describing the object + /// + /// String description of the object + //////////////////////////////////////////////////////////// + public override string ToString() + { + if (IsInvalid) { - if (IsInvalid) - { - return MakeDisposedObjectString(); - } - - return "[Sound]" + - " Status(" + Status + ")" + - " IsLooping(" + IsLooping + ")" + - " Pitch(" + Pitch + ")" + - " Volume(" + Volume + ")" + - " Position(" + Position + ")" + - " RelativeToListener(" + RelativeToListener + ")" + - " MinDistance(" + MinDistance + ")" + - " Attenuation(" + Attenuation + ")" + - " PlayingOffset(" + PlayingOffset + ")" + - " SoundBuffer(" + SoundBuffer + ")"; + return MakeDisposedObjectString(); } - //////////////////////////////////////////////////////////// - /// - /// Handle the destruction of the object - /// - /// Is the GC disposing the object, or is it an explicit call ? - //////////////////////////////////////////////////////////// - protected override void Destroy(bool disposing) => sfSound_destroy(CPointer); + return "[Sound]" + + " Status(" + Status + ")" + + " IsLooping(" + IsLooping + ")" + + " Pitch(" + Pitch + ")" + + " Volume(" + Volume + ")" + + " Position(" + Position + ")" + + " RelativeToListener(" + RelativeToListener + ")" + + " MinDistance(" + MinDistance + ")" + + " Attenuation(" + Attenuation + ")" + + " PlayingOffset(" + PlayingOffset + ")" + + " SoundBuffer(" + SoundBuffer + ")"; + } + + //////////////////////////////////////////////////////////// + /// + /// Handle the destruction of the object + /// + /// Is the GC disposing the object, or is it an explicit call ? + //////////////////////////////////////////////////////////// + protected override void Destroy(bool disposing) => sfSound_destroy(CPointer); - private SoundBuffer _buffer; - private EffectProcessorInternal _effectProcessor; + private SoundBuffer _buffer; + private EffectProcessorInternal _effectProcessor; - #region Imports - [DllImport(CSFML.Audio, CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] - private static extern IntPtr sfSound_create(IntPtr soundBuffer); + #region Imports + [DllImport(CSFML.Audio, CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] + private static extern IntPtr sfSound_create(IntPtr soundBuffer); - [DllImport(CSFML.Audio, CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] - private static extern IntPtr sfSound_copy(IntPtr sound); + [DllImport(CSFML.Audio, CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] + private static extern IntPtr sfSound_copy(IntPtr sound); - [DllImport(CSFML.Audio, CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] - private static extern void sfSound_destroy(IntPtr sound); + [DllImport(CSFML.Audio, CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] + private static extern void sfSound_destroy(IntPtr sound); - [DllImport(CSFML.Audio, CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] - private static extern void sfSound_play(IntPtr sound); + [DllImport(CSFML.Audio, CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] + private static extern void sfSound_play(IntPtr sound); - [DllImport(CSFML.Audio, CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] - private static extern void sfSound_pause(IntPtr sound); + [DllImport(CSFML.Audio, CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] + private static extern void sfSound_pause(IntPtr sound); - [DllImport(CSFML.Audio, CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] - private static extern void sfSound_stop(IntPtr sound); + [DllImport(CSFML.Audio, CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] + private static extern void sfSound_stop(IntPtr sound); - [DllImport(CSFML.Audio, CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] - private static extern void sfSound_setBuffer(IntPtr sound, IntPtr buffer); + [DllImport(CSFML.Audio, CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] + private static extern void sfSound_setBuffer(IntPtr sound, IntPtr buffer); - [DllImport(CSFML.Audio, CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] - private static extern void sfSound_setLooping(IntPtr sound, bool loop); + [DllImport(CSFML.Audio, CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] + private static extern void sfSound_setLooping(IntPtr sound, bool loop); - [DllImport(CSFML.Audio, CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] - [return: MarshalAs(UnmanagedType.I1)] - private static extern bool sfSound_isLooping(IntPtr sound); + [DllImport(CSFML.Audio, CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] + [return: MarshalAs(UnmanagedType.I1)] + private static extern bool sfSound_isLooping(IntPtr sound); - [DllImport(CSFML.Audio, CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] - private static extern SoundStatus sfSound_getStatus(IntPtr sound); + [DllImport(CSFML.Audio, CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] + private static extern SoundStatus sfSound_getStatus(IntPtr sound); - [DllImport(CSFML.Audio, CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] - private static extern void sfSound_setPitch(IntPtr sound, float pitch); + [DllImport(CSFML.Audio, CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] + private static extern void sfSound_setPitch(IntPtr sound, float pitch); - [DllImport(CSFML.Audio, CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] - private static extern void sfSound_setPan(IntPtr sound, float pan); + [DllImport(CSFML.Audio, CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] + private static extern void sfSound_setPan(IntPtr sound, float pan); - [DllImport(CSFML.Audio, CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] - private static extern void sfSound_setVolume(IntPtr sound, float volume); + [DllImport(CSFML.Audio, CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] + private static extern void sfSound_setVolume(IntPtr sound, float volume); - [DllImport(CSFML.Audio, CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] - private static extern void sfSound_setSpatializationEnabled(IntPtr sound, bool enabled); + [DllImport(CSFML.Audio, CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] + private static extern void sfSound_setSpatializationEnabled(IntPtr sound, bool enabled); - [DllImport(CSFML.Audio, CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] - private static extern void sfSound_setPosition(IntPtr sound, Vector3f position); + [DllImport(CSFML.Audio, CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] + private static extern void sfSound_setPosition(IntPtr sound, Vector3f position); - [DllImport(CSFML.Audio, CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] - private static extern void sfSound_setDirection(IntPtr sound, Vector3f direction); + [DllImport(CSFML.Audio, CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] + private static extern void sfSound_setDirection(IntPtr sound, Vector3f direction); - [DllImport(CSFML.Audio, CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] - private static extern void sfSound_setCone(IntPtr sound, Cone.MarshalData cone); + [DllImport(CSFML.Audio, CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] + private static extern void sfSound_setCone(IntPtr sound, Cone.MarshalData cone); - [DllImport(CSFML.Audio, CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] - private static extern void sfSound_setVelocity(IntPtr sound, Vector3f velocity); + [DllImport(CSFML.Audio, CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] + private static extern void sfSound_setVelocity(IntPtr sound, Vector3f velocity); - [DllImport(CSFML.Audio, CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] - private static extern void sfSound_setDopplerFactor(IntPtr sound, float factor); + [DllImport(CSFML.Audio, CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] + private static extern void sfSound_setDopplerFactor(IntPtr sound, float factor); - [DllImport(CSFML.Audio, CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] - private static extern void sfSound_setDirectionalAttenuationFactor(IntPtr sound, float factor); + [DllImport(CSFML.Audio, CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] + private static extern void sfSound_setDirectionalAttenuationFactor(IntPtr sound, float factor); - [DllImport(CSFML.Audio, CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] - private static extern void sfSound_setRelativeToListener(IntPtr sound, bool relative); + [DllImport(CSFML.Audio, CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] + private static extern void sfSound_setRelativeToListener(IntPtr sound, bool relative); - [DllImport(CSFML.Audio, CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] - private static extern void sfSound_setMinDistance(IntPtr sound, float minDistance); + [DllImport(CSFML.Audio, CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] + private static extern void sfSound_setMinDistance(IntPtr sound, float minDistance); - [DllImport(CSFML.Audio, CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] - private static extern void sfSound_setMaxDistance(IntPtr sound, float maxDistance); + [DllImport(CSFML.Audio, CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] + private static extern void sfSound_setMaxDistance(IntPtr sound, float maxDistance); - [DllImport(CSFML.Audio, CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] - private static extern void sfSound_setMinGain(IntPtr sound, float gain); + [DllImport(CSFML.Audio, CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] + private static extern void sfSound_setMinGain(IntPtr sound, float gain); - [DllImport(CSFML.Audio, CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] - private static extern void sfSound_setMaxGain(IntPtr sound, float gain); + [DllImport(CSFML.Audio, CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] + private static extern void sfSound_setMaxGain(IntPtr sound, float gain); - [DllImport(CSFML.Audio, CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] - private static extern void sfSound_setAttenuation(IntPtr sound, float attenuation); + [DllImport(CSFML.Audio, CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] + private static extern void sfSound_setAttenuation(IntPtr sound, float attenuation); - [DllImport(CSFML.Audio, CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] - private static extern void sfSound_setPlayingOffset(IntPtr sound, Time timeOffset); + [DllImport(CSFML.Audio, CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] + private static extern void sfSound_setPlayingOffset(IntPtr sound, Time timeOffset); - [DllImport(CSFML.Audio, CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] - private static extern void sfSound_setEffectProcessor(IntPtr sound, IntPtr effectProcessor); + [DllImport(CSFML.Audio, CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] + private static extern void sfSound_setEffectProcessor(IntPtr sound, IntPtr effectProcessor); - [DllImport(CSFML.Audio, CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] - private static extern float sfSound_getPitch(IntPtr sound); + [DllImport(CSFML.Audio, CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] + private static extern float sfSound_getPitch(IntPtr sound); - [DllImport(CSFML.Audio, CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] - private static extern float sfSound_getPan(IntPtr sound); + [DllImport(CSFML.Audio, CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] + private static extern float sfSound_getPan(IntPtr sound); - [DllImport(CSFML.Audio, CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] - private static extern float sfSound_getVolume(IntPtr sound); + [DllImport(CSFML.Audio, CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] + private static extern float sfSound_getVolume(IntPtr sound); - [DllImport(CSFML.Audio, CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] - [return: MarshalAs(UnmanagedType.I1)] - private static extern bool sfSound_isSpatializationEnabled(IntPtr sound); + [DllImport(CSFML.Audio, CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] + [return: MarshalAs(UnmanagedType.I1)] + private static extern bool sfSound_isSpatializationEnabled(IntPtr sound); - [DllImport(CSFML.Audio, CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] - private static extern Vector3f sfSound_getPosition(IntPtr sound); + [DllImport(CSFML.Audio, CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] + private static extern Vector3f sfSound_getPosition(IntPtr sound); - [DllImport(CSFML.Audio, CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] - private static extern Vector3f sfSound_getDirection(IntPtr sound); + [DllImport(CSFML.Audio, CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] + private static extern Vector3f sfSound_getDirection(IntPtr sound); - [DllImport(CSFML.Audio, CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] - private static extern Cone.MarshalData sfSound_getCone(IntPtr sound); + [DllImport(CSFML.Audio, CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] + private static extern Cone.MarshalData sfSound_getCone(IntPtr sound); - [DllImport(CSFML.Audio, CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] - private static extern Vector3f sfSound_getVelocity(IntPtr sound); + [DllImport(CSFML.Audio, CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] + private static extern Vector3f sfSound_getVelocity(IntPtr sound); - [DllImport(CSFML.Audio, CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] - private static extern float sfSound_getDopplerFactor(IntPtr sound); + [DllImport(CSFML.Audio, CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] + private static extern float sfSound_getDopplerFactor(IntPtr sound); - [DllImport(CSFML.Audio, CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] - private static extern float sfSound_getDirectionalAttenuationFactor(IntPtr sound); + [DllImport(CSFML.Audio, CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] + private static extern float sfSound_getDirectionalAttenuationFactor(IntPtr sound); - [DllImport(CSFML.Audio, CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] - [return: MarshalAs(UnmanagedType.I1)] - private static extern bool sfSound_isRelativeToListener(IntPtr sound); + [DllImport(CSFML.Audio, CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] + [return: MarshalAs(UnmanagedType.I1)] + private static extern bool sfSound_isRelativeToListener(IntPtr sound); - [DllImport(CSFML.Audio, CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] - private static extern float sfSound_getMinDistance(IntPtr sound); + [DllImport(CSFML.Audio, CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] + private static extern float sfSound_getMinDistance(IntPtr sound); - [DllImport(CSFML.Audio, CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] - private static extern float sfSound_getMaxDistance(IntPtr sound); + [DllImport(CSFML.Audio, CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] + private static extern float sfSound_getMaxDistance(IntPtr sound); - [DllImport(CSFML.Audio, CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] - private static extern float sfSound_getMinGain(IntPtr sound); + [DllImport(CSFML.Audio, CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] + private static extern float sfSound_getMinGain(IntPtr sound); - [DllImport(CSFML.Audio, CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] - private static extern float sfSound_getMaxGain(IntPtr sound); + [DllImport(CSFML.Audio, CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] + private static extern float sfSound_getMaxGain(IntPtr sound); - [DllImport(CSFML.Audio, CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] - private static extern float sfSound_getAttenuation(IntPtr sound); + [DllImport(CSFML.Audio, CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] + private static extern float sfSound_getAttenuation(IntPtr sound); - [DllImport(CSFML.Audio, CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] - private static extern Time sfSound_getPlayingOffset(IntPtr sound); - #endregion - } + [DllImport(CSFML.Audio, CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] + private static extern Time sfSound_getPlayingOffset(IntPtr sound); + #endregion } diff --git a/src/SFML.Audio/SoundBuffer.cs b/src/SFML.Audio/SoundBuffer.cs index fc756449..e45ea880 100644 --- a/src/SFML.Audio/SoundBuffer.cs +++ b/src/SFML.Audio/SoundBuffer.cs @@ -4,278 +4,277 @@ using System.Security; using SFML.System; -namespace SFML.Audio +namespace SFML.Audio; + +//////////////////////////////////////////////////////////// +/// +/// Storage for audio samples defining a sound +/// +//////////////////////////////////////////////////////////// +public class SoundBuffer : ObjectBase { //////////////////////////////////////////////////////////// /// - /// Storage for audio samples defining a sound + /// Construct a sound buffer from a file + /// + /// Here is a complete list of all the supported audio formats: + /// ogg, wav, flac, mp3, aiff, au, raw, paf, svx, nist, voc, ircam, + /// w64, mat4, mat5 pvf, htk, sds, avr, sd2, caf, wve, mpc2k, rf64. /// + /// Path of the sound file to load + /// //////////////////////////////////////////////////////////// - public class SoundBuffer : ObjectBase + public SoundBuffer(string filename) : + base(sfSoundBuffer_createFromFile(filename)) { - //////////////////////////////////////////////////////////// - /// - /// Construct a sound buffer from a file - /// - /// Here is a complete list of all the supported audio formats: - /// ogg, wav, flac, mp3, aiff, au, raw, paf, svx, nist, voc, ircam, - /// w64, mat4, mat5 pvf, htk, sds, avr, sd2, caf, wve, mpc2k, rf64. - /// - /// Path of the sound file to load - /// - //////////////////////////////////////////////////////////// - public SoundBuffer(string filename) : - base(sfSoundBuffer_createFromFile(filename)) + if (IsInvalid) { - if (IsInvalid) - { - throw new LoadingFailedException("sound buffer", filename); - } + throw new LoadingFailedException("sound buffer", filename); } + } - //////////////////////////////////////////////////////////// - /// - /// Construct a sound buffer from a custom stream. - /// - /// Here is a complete list of all the supported audio formats: - /// ogg, wav, flac, mp3, aiff, au, raw, paf, svx, nist, voc, ircam, - /// w64, mat4, mat5 pvf, htk, sds, avr, sd2, caf, wve, mpc2k, rf64. - /// - /// Source stream to read from - /// - //////////////////////////////////////////////////////////// - public SoundBuffer(Stream stream) : - base(IntPtr.Zero) + //////////////////////////////////////////////////////////// + /// + /// Construct a sound buffer from a custom stream. + /// + /// Here is a complete list of all the supported audio formats: + /// ogg, wav, flac, mp3, aiff, au, raw, paf, svx, nist, voc, ircam, + /// w64, mat4, mat5 pvf, htk, sds, avr, sd2, caf, wve, mpc2k, rf64. + /// + /// Source stream to read from + /// + //////////////////////////////////////////////////////////// + public SoundBuffer(Stream stream) : + base(IntPtr.Zero) + { + using (var adaptor = new StreamAdaptor(stream)) { - using (var adaptor = new StreamAdaptor(stream)) - { - CPointer = sfSoundBuffer_createFromStream(adaptor.InputStreamPtr); - } + CPointer = sfSoundBuffer_createFromStream(adaptor.InputStreamPtr); + } - if (IsInvalid) - { - throw new LoadingFailedException("sound buffer"); - } + if (IsInvalid) + { + throw new LoadingFailedException("sound buffer"); } + } - //////////////////////////////////////////////////////////// - /// - /// Construct a sound buffer from a file in memory. - /// - /// Here is a complete list of all the supported audio formats: - /// ogg, wav, flac, mp3, aiff, au, raw, paf, svx, nist, voc, ircam, - /// w64, mat4, mat5 pvf, htk, sds, avr, sd2, caf, wve, mpc2k, rf64. - /// - /// Byte array containing the file contents - /// - //////////////////////////////////////////////////////////// - public SoundBuffer(byte[] bytes) : - base(IntPtr.Zero) + //////////////////////////////////////////////////////////// + /// + /// Construct a sound buffer from a file in memory. + /// + /// Here is a complete list of all the supported audio formats: + /// ogg, wav, flac, mp3, aiff, au, raw, paf, svx, nist, voc, ircam, + /// w64, mat4, mat5 pvf, htk, sds, avr, sd2, caf, wve, mpc2k, rf64. + /// + /// Byte array containing the file contents + /// + //////////////////////////////////////////////////////////// + public SoundBuffer(byte[] bytes) : + base(IntPtr.Zero) + { + unsafe { - unsafe + fixed (void* ptr = bytes) { - fixed (void* ptr = bytes) - { - CPointer = sfSoundBuffer_createFromMemory((IntPtr)ptr, (UIntPtr)bytes.Length); - } + CPointer = sfSoundBuffer_createFromMemory((IntPtr)ptr, (UIntPtr)bytes.Length); } + } - if (IsInvalid) - { - throw new LoadingFailedException("sound buffer"); - } + if (IsInvalid) + { + throw new LoadingFailedException("sound buffer"); } + } - //////////////////////////////////////////////////////////// - /// - /// Construct a sound buffer from an array of samples - /// - /// Array of samples - /// Channel count - /// Sample rate - /// Map of position in sample frame to sound channel - /// - //////////////////////////////////////////////////////////// - public SoundBuffer(short[] samples, uint channelCount, uint sampleRate, SoundChannel[] channelMapData) : - base(IntPtr.Zero) + //////////////////////////////////////////////////////////// + /// + /// Construct a sound buffer from an array of samples + /// + /// Array of samples + /// Channel count + /// Sample rate + /// Map of position in sample frame to sound channel + /// + //////////////////////////////////////////////////////////// + public SoundBuffer(short[] samples, uint channelCount, uint sampleRate, SoundChannel[] channelMapData) : + base(IntPtr.Zero) + { + unsafe { - unsafe + fixed (short* samplesPtr = samples) { - fixed (short* samplesPtr = samples) + fixed (SoundChannel* channels = channelMapData) { - fixed (SoundChannel* channels = channelMapData) - { - CPointer = sfSoundBuffer_createFromSamples(samplesPtr, (uint)samples.Length, channelCount, sampleRate, channels, (UIntPtr)channelMapData.Length); - } + CPointer = sfSoundBuffer_createFromSamples(samplesPtr, (uint)samples.Length, channelCount, sampleRate, channels, (UIntPtr)channelMapData.Length); } } - - if (IsInvalid) - { - throw new LoadingFailedException("sound buffer"); - } } - //////////////////////////////////////////////////////////// - /// - /// Construct a sound buffer from another sound buffer - /// - /// Sound buffer to copy - //////////////////////////////////////////////////////////// - public SoundBuffer(SoundBuffer copy) : - base(sfSoundBuffer_copy(copy.CPointer)) + if (IsInvalid) { + throw new LoadingFailedException("sound buffer"); } + } + + //////////////////////////////////////////////////////////// + /// + /// Construct a sound buffer from another sound buffer + /// + /// Sound buffer to copy + //////////////////////////////////////////////////////////// + public SoundBuffer(SoundBuffer copy) : + base(sfSoundBuffer_copy(copy.CPointer)) + { + } + + //////////////////////////////////////////////////////////// + /// + /// Save the sound buffer to an audio file. + /// + /// Here is a complete list of all the supported audio formats: + /// ogg, wav, flac, mp3, aiff, au, raw, paf, svx, nist, voc, ircam, + /// w64, mat4, mat5 pvf, htk, sds, avr, sd2, caf, wve, mpc2k, rf64. + /// + /// Path of the sound file to write + /// True if saving has been successful + //////////////////////////////////////////////////////////// + public bool SaveToFile(string filename) => sfSoundBuffer_saveToFile(CPointer, filename); - //////////////////////////////////////////////////////////// - /// - /// Save the sound buffer to an audio file. - /// - /// Here is a complete list of all the supported audio formats: - /// ogg, wav, flac, mp3, aiff, au, raw, paf, svx, nist, voc, ircam, - /// w64, mat4, mat5 pvf, htk, sds, avr, sd2, caf, wve, mpc2k, rf64. - /// - /// Path of the sound file to write - /// True if saving has been successful - //////////////////////////////////////////////////////////// - public bool SaveToFile(string filename) => sfSoundBuffer_saveToFile(CPointer, filename); - - //////////////////////////////////////////////////////////// - /// - /// Sample rate of the sound buffer. - /// - /// The sample rate is the number of audio samples played per - /// second. The higher, the better the quality. - /// - //////////////////////////////////////////////////////////// - public uint SampleRate => sfSoundBuffer_getSampleRate(CPointer); - - //////////////////////////////////////////////////////////// - /// - /// Number of channels (1 = mono, 2 = stereo) - /// - //////////////////////////////////////////////////////////// - public uint ChannelCount => sfSoundBuffer_getChannelCount(CPointer); - - //////////////////////////////////////////////////////////// - /// - /// Total duration of the buffer - /// - //////////////////////////////////////////////////////////// - public Time Duration => sfSoundBuffer_getDuration(CPointer); - - //////////////////////////////////////////////////////////// - /// - /// Array of audio samples stored in the buffer. - /// - /// The format of the returned samples is 16 bits signed integer - /// (sf::Int16). - /// - //////////////////////////////////////////////////////////// - public short[] Samples + //////////////////////////////////////////////////////////// + /// + /// Sample rate of the sound buffer. + /// + /// The sample rate is the number of audio samples played per + /// second. The higher, the better the quality. + /// + //////////////////////////////////////////////////////////// + public uint SampleRate => sfSoundBuffer_getSampleRate(CPointer); + + //////////////////////////////////////////////////////////// + /// + /// Number of channels (1 = mono, 2 = stereo) + /// + //////////////////////////////////////////////////////////// + public uint ChannelCount => sfSoundBuffer_getChannelCount(CPointer); + + //////////////////////////////////////////////////////////// + /// + /// Total duration of the buffer + /// + //////////////////////////////////////////////////////////// + public Time Duration => sfSoundBuffer_getDuration(CPointer); + + //////////////////////////////////////////////////////////// + /// + /// Array of audio samples stored in the buffer. + /// + /// The format of the returned samples is 16 bits signed integer + /// (sf::Int16). + /// + //////////////////////////////////////////////////////////// + public short[] Samples + { + get { - get - { - var samplesArray = new short[sfSoundBuffer_getSampleCount(CPointer)]; - Marshal.Copy(sfSoundBuffer_getSamples(CPointer), samplesArray, 0, samplesArray.Length); - return samplesArray; - } + var samplesArray = new short[sfSoundBuffer_getSampleCount(CPointer)]; + Marshal.Copy(sfSoundBuffer_getSamples(CPointer), samplesArray, 0, samplesArray.Length); + return samplesArray; } + } - //////////////////////////////////////////////////////////// - /// - /// 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 spatialisation. - /// - //////////////////////////////////////////////////////////// - public virtual SoundChannel[] ChannelMap + //////////////////////////////////////////////////////////// + /// + /// 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 spatialisation. + /// + //////////////////////////////////////////////////////////// + public virtual SoundChannel[] ChannelMap + { + get { - get + unsafe { - unsafe - { - var channels = sfSoundBuffer_getChannelMap(CPointer, out var count); - var arr = new SoundChannel[(int)count]; - - for (var i = 0; i < arr.Length; i++) - { - arr[i] = channels[i]; - } + var channels = sfSoundBuffer_getChannelMap(CPointer, out var count); + var arr = new SoundChannel[(int)count]; - return arr; + for (var i = 0; i < arr.Length; i++) + { + arr[i] = channels[i]; } + + return arr; } } + } - //////////////////////////////////////////////////////////// - /// - /// Provide a string describing the object - /// - /// String description of the object - //////////////////////////////////////////////////////////// - public override string ToString() + //////////////////////////////////////////////////////////// + /// + /// Provide a string describing the object + /// + /// String description of the object + //////////////////////////////////////////////////////////// + public override string ToString() + { + if (IsInvalid) { - if (IsInvalid) - { - return MakeDisposedObjectString(); - } - - return "[SoundBuffer]" + - " SampleRate(" + SampleRate + ")" + - " ChannelCount(" + ChannelCount + ")" + - " Duration(" + Duration + ")"; + return MakeDisposedObjectString(); } - //////////////////////////////////////////////////////////// - /// - /// Handle the destruction of the object - /// - /// Is the GC disposing the object, or is it an explicit call ? - //////////////////////////////////////////////////////////// - protected override void Destroy(bool disposing) => sfSoundBuffer_destroy(CPointer); + return "[SoundBuffer]" + + " SampleRate(" + SampleRate + ")" + + " ChannelCount(" + ChannelCount + ")" + + " Duration(" + Duration + ")"; + } + + //////////////////////////////////////////////////////////// + /// + /// Handle the destruction of the object + /// + /// Is the GC disposing the object, or is it an explicit call ? + //////////////////////////////////////////////////////////// + protected override void Destroy(bool disposing) => sfSoundBuffer_destroy(CPointer); - #region Imports - [DllImport(CSFML.Audio, CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] - private static extern IntPtr sfSoundBuffer_createFromFile(string filename); + #region Imports + [DllImport(CSFML.Audio, CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] + private static extern IntPtr sfSoundBuffer_createFromFile(string filename); - [DllImport(CSFML.Audio, CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] - private static extern unsafe IntPtr sfSoundBuffer_createFromStream(IntPtr stream); + [DllImport(CSFML.Audio, CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] + private static extern IntPtr sfSoundBuffer_createFromStream(IntPtr stream); - [DllImport(CSFML.Audio, CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] - private static extern unsafe IntPtr sfSoundBuffer_createFromMemory(IntPtr data, UIntPtr size); + [DllImport(CSFML.Audio, CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] + private static extern IntPtr sfSoundBuffer_createFromMemory(IntPtr data, UIntPtr size); - [DllImport(CSFML.Audio, CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] - private static extern unsafe IntPtr sfSoundBuffer_createFromSamples(short* samples, ulong sampleCount, uint channelsCount, uint sampleRate, SoundChannel* channelMapData, UIntPtr channelMapSize); + [DllImport(CSFML.Audio, CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] + private static extern unsafe IntPtr sfSoundBuffer_createFromSamples(short* samples, ulong sampleCount, uint channelsCount, uint sampleRate, SoundChannel* channelMapData, UIntPtr channelMapSize); - [DllImport(CSFML.Audio, CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] - private static extern IntPtr sfSoundBuffer_copy(IntPtr soundBuffer); + [DllImport(CSFML.Audio, CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] + private static extern IntPtr sfSoundBuffer_copy(IntPtr soundBuffer); - [DllImport(CSFML.Audio, CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] - private static extern void sfSoundBuffer_destroy(IntPtr soundBuffer); + [DllImport(CSFML.Audio, CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] + private static extern void sfSoundBuffer_destroy(IntPtr soundBuffer); - [DllImport(CSFML.Audio, CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] - [return: MarshalAs(UnmanagedType.I1)] - private static extern bool sfSoundBuffer_saveToFile(IntPtr soundBuffer, string filename); + [DllImport(CSFML.Audio, CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] + [return: MarshalAs(UnmanagedType.I1)] + private static extern bool sfSoundBuffer_saveToFile(IntPtr soundBuffer, string filename); - [DllImport(CSFML.Audio, CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] - private static extern IntPtr sfSoundBuffer_getSamples(IntPtr soundBuffer); + [DllImport(CSFML.Audio, CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] + private static extern IntPtr sfSoundBuffer_getSamples(IntPtr soundBuffer); - [DllImport(CSFML.Audio, CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] - private static extern ulong sfSoundBuffer_getSampleCount(IntPtr soundBuffer); + [DllImport(CSFML.Audio, CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] + private static extern ulong sfSoundBuffer_getSampleCount(IntPtr soundBuffer); - [DllImport(CSFML.Audio, CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] - private static extern uint sfSoundBuffer_getSampleRate(IntPtr soundBuffer); + [DllImport(CSFML.Audio, CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] + private static extern uint sfSoundBuffer_getSampleRate(IntPtr soundBuffer); - [DllImport(CSFML.Audio, CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] - private static extern uint sfSoundBuffer_getChannelCount(IntPtr soundBuffer); + [DllImport(CSFML.Audio, CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] + private static extern uint sfSoundBuffer_getChannelCount(IntPtr soundBuffer); - [DllImport(CSFML.Audio, CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] - private static extern unsafe SoundChannel* sfSoundBuffer_getChannelMap(IntPtr soundBuffer, out UIntPtr count); + [DllImport(CSFML.Audio, CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] + private static extern unsafe SoundChannel* sfSoundBuffer_getChannelMap(IntPtr soundBuffer, out UIntPtr count); - [DllImport(CSFML.Audio, CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] - private static extern Time sfSoundBuffer_getDuration(IntPtr soundBuffer); - #endregion - } + [DllImport(CSFML.Audio, CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] + private static extern Time sfSoundBuffer_getDuration(IntPtr soundBuffer); + #endregion } diff --git a/src/SFML.Audio/SoundBufferRecorder.cs b/src/SFML.Audio/SoundBufferRecorder.cs index 98c885d4..9258a135 100644 --- a/src/SFML.Audio/SoundBufferRecorder.cs +++ b/src/SFML.Audio/SoundBufferRecorder.cs @@ -1,81 +1,80 @@ using System.Collections.Generic; -namespace SFML.Audio +namespace SFML.Audio; + +//////////////////////////////////////////////////////////// +/// +/// Specialized SoundRecorder which saves the captured +/// audio data into a sound buffer +/// +//////////////////////////////////////////////////////////// +public class SoundBufferRecorder : SoundRecorder { //////////////////////////////////////////////////////////// /// - /// Specialized SoundRecorder which saves the captured - /// audio data into a sound buffer + /// Sound buffer containing the captured audio data + /// + /// The sound buffer is valid only after the capture has ended. + /// This function provides a reference to the internal + /// sound buffer, but you should make a copy of it if you want + /// to make any modifications to it. /// //////////////////////////////////////////////////////////// - public class SoundBufferRecorder : SoundRecorder - { - //////////////////////////////////////////////////////////// - /// - /// Sound buffer containing the captured audio data - /// - /// The sound buffer is valid only after the capture has ended. - /// This function provides a reference to the internal - /// sound buffer, but you should make a copy of it if you want - /// to make any modifications to it. - /// - //////////////////////////////////////////////////////////// - public SoundBuffer SoundBuffer { get; private set; } - - //////////////////////////////////////////////////////////// - /// - /// Provide a string describing the object - /// - /// String description of the object - //////////////////////////////////////////////////////////// - public override string ToString() - { - if (IsInvalid) - { - return MakeDisposedObjectString(); - } + public SoundBuffer SoundBuffer { get; private set; } - return "[SoundBufferRecorder]" + - " SampleRate(" + SampleRate + ")" + - " SoundBuffer(" + SoundBuffer + ")"; - } - - //////////////////////////////////////////////////////////// - /// - /// Called when a new capture starts - /// - /// False to abort recording audio data, true to continue - //////////////////////////////////////////////////////////// - protected override bool OnStart() + //////////////////////////////////////////////////////////// + /// + /// Provide a string describing the object + /// + /// String description of the object + //////////////////////////////////////////////////////////// + public override string ToString() + { + if (IsInvalid) { - _samplesArray.Clear(); - return true; + return MakeDisposedObjectString(); } - //////////////////////////////////////////////////////////// - /// - /// Process a new chunk of recorded samples - /// - /// Array of samples to process - /// False to stop recording audio data, true to continue - //////////////////////////////////////////////////////////// - protected override bool OnProcessSamples(short[] samples) - { - _samplesArray.AddRange(samples); - return true; - } + return "[SoundBufferRecorder]" + + " SampleRate(" + SampleRate + ")" + + " SoundBuffer(" + SoundBuffer + ")"; + } - //////////////////////////////////////////////////////////// - /// - /// Called when the current capture stops - /// - //////////////////////////////////////////////////////////// - protected override void OnStop() => SoundBuffer = new SoundBuffer(_samplesArray.ToArray(), 1, SampleRate, _channels); + //////////////////////////////////////////////////////////// + /// + /// Called when a new capture starts + /// + /// False to abort recording audio data, true to continue + //////////////////////////////////////////////////////////// + protected override bool OnStart() + { + _samplesArray.Clear(); + return true; + } - private readonly List _samplesArray = new List(); - private static readonly SoundChannel[] _channels = new SoundChannel[] - { - SoundChannel.Mono - }; + //////////////////////////////////////////////////////////// + /// + /// Process a new chunk of recorded samples + /// + /// Array of samples to process + /// False to stop recording audio data, true to continue + //////////////////////////////////////////////////////////// + protected override bool OnProcessSamples(short[] samples) + { + _samplesArray.AddRange(samples); + return true; } + + //////////////////////////////////////////////////////////// + /// + /// Called when the current capture stops + /// + //////////////////////////////////////////////////////////// + protected override void OnStop() => SoundBuffer = new SoundBuffer([.. _samplesArray], 1, SampleRate, _channels); + + private readonly List _samplesArray = []; + private static readonly SoundChannel[] _channels = + [ + SoundChannel.Mono + ]; } diff --git a/src/SFML.Audio/SoundChannel.cs b/src/SFML.Audio/SoundChannel.cs index 0aa04e9d..723e750a 100644 --- a/src/SFML.Audio/SoundChannel.cs +++ b/src/SFML.Audio/SoundChannel.cs @@ -1,40 +1,40 @@ -namespace SFML.Audio -{ - //////////////////////////////////////////////////////////// - /// - /// 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 spatialised. Assigning an incorrect sound channel - /// will result in multi-channel audio being positioned - /// incorrectly when using spatialisation. - /// - //////////////////////////////////////////////////////////// +namespace SFML.Audio; + +//////////////////////////////////////////////////////////// +/// +/// 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 spatialised. Assigning an incorrect sound channel +/// will result in multi-channel audio being positioned +/// incorrectly when using spatialisation. +/// +//////////////////////////////////////////////////////////// #pragma warning disable CS1591 // TODO: add documentation when available - public enum SoundChannel - { - Unspecified, - Mono, - FrontLeft, - FrontRight, - FrontCenter, - FrontLeftOfCenter, - FrontRightOfCenter, - LowFrequencyEffects, - BackLeft, - BackRight, - BackCenter, - SideLeft, - SideRight, - TopCenter, - TopFrontLeft, - TopFrontRight, - TopFrontCenter, - TopBackLeft, - TopBackRight, - TopBackCenter - } -#pragma warning restore CS1591 +public enum SoundChannel +{ + Unspecified, + Mono, + FrontLeft, + FrontRight, + FrontCenter, + FrontLeftOfCenter, + FrontRightOfCenter, + LowFrequencyEffects, + BackLeft, + BackRight, + BackCenter, + SideLeft, + SideRight, + TopCenter, + TopFrontLeft, + TopFrontRight, + TopFrontCenter, + TopBackLeft, + TopBackRight, + TopBackCenter } +#pragma warning restore CS1591 + diff --git a/src/SFML.Audio/SoundRecorder.cs b/src/SFML.Audio/SoundRecorder.cs index ed5a7318..d41640df 100644 --- a/src/SFML.Audio/SoundRecorder.cs +++ b/src/SFML.Audio/SoundRecorder.cs @@ -3,340 +3,339 @@ using System.Security; using SFML.System; -namespace SFML.Audio +namespace SFML.Audio; + +//////////////////////////////////////////////////////////// +/// +/// Base class intended for capturing sound data +/// +//////////////////////////////////////////////////////////// +public abstract class SoundRecorder : ObjectBase { //////////////////////////////////////////////////////////// /// - /// Base class intended for capturing sound data + /// Default constructor /// //////////////////////////////////////////////////////////// - public abstract class SoundRecorder : ObjectBase + protected SoundRecorder() : + base(IntPtr.Zero) { - //////////////////////////////////////////////////////////// - /// - /// Default constructor - /// - //////////////////////////////////////////////////////////// - public SoundRecorder() : - base(IntPtr.Zero) - { - _startCallback = new StartCallback(StartRecording); - _processCallback = new ProcessCallback(ProcessSamples); - _stopCallback = new StopCallback(StopRecording); + _startCallback = new StartCallback(StartRecording); + _processCallback = new ProcessCallback(ProcessSamples); + _stopCallback = new StopCallback(StopRecording); - CPointer = sfSoundRecorder_create(_startCallback, _processCallback, _stopCallback, IntPtr.Zero); - } + CPointer = sfSoundRecorder_create(_startCallback, _processCallback, _stopCallback, IntPtr.Zero); + } - //////////////////////////////////////////////////////////// - /// - /// Start the capture using the default sample rate (44100 Hz). - /// - /// Please note that only one capture can happen at the same time. - /// - //////////////////////////////////////////////////////////// - public bool Start() => Start(44100); - - //////////////////////////////////////////////////////////// - /// - /// 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. - /// - /// Sound frequency; the more samples, the higher the quality (44100 by default = CD quality) - //////////////////////////////////////////////////////////// - public bool Start(uint sampleRate) => sfSoundRecorder_start(CPointer, sampleRate); - - //////////////////////////////////////////////////////////// - /// - /// Stop the capture - /// - //////////////////////////////////////////////////////////// - public void Stop() => sfSoundRecorder_stop(CPointer); - - //////////////////////////////////////////////////////////// - /// - /// Sample rate of the sound recorder. - /// - /// - /// - /// 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). - /// - //////////////////////////////////////////////////////////// - public uint SampleRate => sfSoundRecorder_getSampleRate(CPointer); - - //////////////////////////////////////////////////////////// - /// - /// Get/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 (1) and - /// 16-bit stereo (2) are supported. - /// - //////////////////////////////////////////////////////////// - public uint ChannelCount - { - get => sfSoundRecorder_getChannelCount(CPointer); - set => sfSoundRecorder_setChannelCount(CPointer, value); - } + //////////////////////////////////////////////////////////// + /// + /// Start the capture using the default sample rate (44100 Hz). + /// + /// Please note that only one capture can happen at the same time. + /// + //////////////////////////////////////////////////////////// + public bool Start() => Start(44100); - //////////////////////////////////////////////////////////// - /// - /// 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 spatialisation. - /// - //////////////////////////////////////////////////////////// - public SoundChannel[] ChannelMap - { - get - { - unsafe - { - var channels = sfSoundRecorder_getChannelMap(CPointer, out var count); - var arr = new SoundChannel[(int)count]; + //////////////////////////////////////////////////////////// + /// + /// 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. + /// + /// Sound frequency; the more samples, the higher the quality (44100 by default = CD quality) + //////////////////////////////////////////////////////////// + public bool Start(uint sampleRate) => sfSoundRecorder_start(CPointer, sampleRate); - for (var i = 0; i < arr.Length; i++) - { - arr[i] = channels[i]; - } + //////////////////////////////////////////////////////////// + /// + /// Stop the capture + /// + //////////////////////////////////////////////////////////// + public void Stop() => sfSoundRecorder_stop(CPointer); - return arr; - } - } - } + //////////////////////////////////////////////////////////// + /// + /// Sample rate of the sound recorder. + /// + /// + /// + /// 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). + /// + //////////////////////////////////////////////////////////// + public uint SampleRate => sfSoundRecorder_getSampleRate(CPointer); + + //////////////////////////////////////////////////////////// + /// + /// Get/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 (1) and + /// 16-bit stereo (2) are supported. + /// + //////////////////////////////////////////////////////////// + public uint ChannelCount + { + get => sfSoundRecorder_getChannelCount(CPointer); + set => sfSoundRecorder_setChannelCount(CPointer, value); + } - //////////////////////////////////////////////////////////// - /// - /// 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 the SoundRecorder or one of its derived - /// classes will fail. - /// - //////////////////////////////////////////////////////////// - public static bool IsAvailable => sfSoundRecorder_isAvailable(); - - //////////////////////////////////////////////////////////// - /// - /// Provide a string describing the object - /// - /// String description of the object - //////////////////////////////////////////////////////////// - public override string ToString() + //////////////////////////////////////////////////////////// + /// + /// 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 spatialisation. + /// + //////////////////////////////////////////////////////////// + public SoundChannel[] ChannelMap + { + get { - if (IsInvalid) + unsafe { - return MakeDisposedObjectString(); - } + var channels = sfSoundRecorder_getChannelMap(CPointer, out var count); + var arr = new SoundChannel[(int)count]; - return "[SoundRecorder]" + " SampleRate(" + SampleRate + ")"; + for (var i = 0; i < arr.Length; i++) + { + arr[i] = channels[i]; + } + + return arr; + } } + } - //////////////////////////////////////////////////////////// - /// - /// 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. - /// - /// False to abort recording audio data, true to continue - //////////////////////////////////////////////////////////// - protected virtual bool OnStart() => - // Does nothing by default - true; - - //////////////////////////////////////////////////////////// - /// - /// 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.). - /// - /// Array of samples to process - /// False to stop recording audio data, true to continue - //////////////////////////////////////////////////////////// - protected abstract bool OnProcessSamples(short[] samples); - - //////////////////////////////////////////////////////////// - /// - /// 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. - /// - //////////////////////////////////////////////////////////// - protected virtual void OnStop() + //////////////////////////////////////////////////////////// + /// + /// 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 the SoundRecorder or one of its derived + /// classes will fail. + /// + //////////////////////////////////////////////////////////// + public static bool IsAvailable => sfSoundRecorder_isAvailable(); + + //////////////////////////////////////////////////////////// + /// + /// Provide a string describing the object + /// + /// String description of the object + //////////////////////////////////////////////////////////// + public override string ToString() + { + if (IsInvalid) { - // Does nothing by default + return MakeDisposedObjectString(); } - //////////////////////////////////////////////////////////// - /// - /// Get the list of the names of all available audio capture devices - /// - //////////////////////////////////////////////////////////// - public static string[] AvailableDevices + return "[SoundRecorder]" + " SampleRate(" + SampleRate + ")"; + } + + //////////////////////////////////////////////////////////// + /// + /// 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. + /// + /// False to abort recording audio data, true to continue + //////////////////////////////////////////////////////////// + protected virtual bool OnStart() => + // Does nothing by default + true; + + //////////////////////////////////////////////////////////// + /// + /// 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.). + /// + /// Array of samples to process + /// False to stop recording audio data, true to continue + //////////////////////////////////////////////////////////// + protected abstract bool OnProcessSamples(short[] samples); + + //////////////////////////////////////////////////////////// + /// + /// 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. + /// + //////////////////////////////////////////////////////////// + protected virtual void OnStop() + { + // Does nothing by default + } + + //////////////////////////////////////////////////////////// + /// + /// Get the list of the names of all available audio capture devices + /// + //////////////////////////////////////////////////////////// + public static string[] AvailableDevices + { + get { - get + unsafe { - unsafe + var devicesPtr = sfSoundRecorder_getAvailableDevices(out var count); + var devices = new string[(int)count]; + for (var i = 0; i < (int)count; ++i) { - var devicesPtr = sfSoundRecorder_getAvailableDevices(out var count); - var devices = new string[(int)count]; - for (var i = 0; i < (int)count; ++i) - { - devices[i] = Marshal.PtrToStringAnsi(devicesPtr[i]); - } - - return devices; + devices[i] = Marshal.PtrToStringAnsi(devicesPtr[i]); } + + return devices; } } + } - //////////////////////////////////////////////////////////// - /// - /// Get the name of the default audio capture device - /// - //////////////////////////////////////////////////////////// - public static string DefaultDevice => Marshal.PtrToStringAnsi(sfSoundRecorder_getDefaultDevice()); - - //////////////////////////////////////////////////////////// - /// - /// Set the audio capture device - /// - /// The name of the audio capture device - /// True, if it was able to set the requested device - //////////////////////////////////////////////////////////// - public bool SetDevice(string name) => sfSoundRecorder_setDevice(CPointer, name); - - //////////////////////////////////////////////////////////// - /// - /// Get the name of the current audio capture device - /// - /// The name of the current audio capture device - //////////////////////////////////////////////////////////// - public string GetDevice() => Marshal.PtrToStringAnsi(sfSoundRecorder_getDevice(CPointer)); - - //////////////////////////////////////////////////////////// - /// - /// Handle the destruction of the object - /// - /// Is the GC disposing the object, or is it an explicit call ? - //////////////////////////////////////////////////////////// - protected override void Destroy(bool disposing) => sfSoundRecorder_destroy(CPointer); - - //////////////////////////////////////////////////////////// - /// - /// Function called directly by the C library ; convert - /// arguments and forward them to the internal virtual function - /// - /// User data -- unused - /// False to stop recording audio data, true to continue - //////////////////////////////////////////////////////////// - private bool StartRecording(IntPtr userData) => OnStart(); - - //////////////////////////////////////////////////////////// - /// - /// Function called directly by the C library ; convert - /// arguments and forward them to the internal virtual function - /// - /// Pointer to the array of samples - /// Number of samples in the array - /// User data -- unused - /// False to stop recording audio data, true to continue - //////////////////////////////////////////////////////////// - private bool ProcessSamples(IntPtr samples, UIntPtr nbSamples, IntPtr userData) - { - var samplesArray = new short[(int)nbSamples]; - Marshal.Copy(samples, samplesArray, 0, samplesArray.Length); + //////////////////////////////////////////////////////////// + /// + /// Get the name of the default audio capture device + /// + //////////////////////////////////////////////////////////// + public static string DefaultDevice => Marshal.PtrToStringAnsi(sfSoundRecorder_getDefaultDevice()); - return OnProcessSamples(samplesArray); - } + //////////////////////////////////////////////////////////// + /// + /// Set the audio capture device + /// + /// The name of the audio capture device + /// True, if it was able to set the requested device + //////////////////////////////////////////////////////////// + public bool SetDevice(string name) => sfSoundRecorder_setDevice(CPointer, name); - //////////////////////////////////////////////////////////// - /// - /// Function called directly by the C library ; convert - /// arguments and forward them to the internal virtual function - /// - /// User data -- unused - //////////////////////////////////////////////////////////// - private void StopRecording(IntPtr userData) => OnStop(); + //////////////////////////////////////////////////////////// + /// + /// Get the name of the current audio capture device + /// + /// The name of the current audio capture device + //////////////////////////////////////////////////////////// + public string GetDevice() => Marshal.PtrToStringAnsi(sfSoundRecorder_getDevice(CPointer)); - [UnmanagedFunctionPointer(CallingConvention.Cdecl)] - private delegate bool StartCallback(IntPtr userData); + //////////////////////////////////////////////////////////// + /// + /// Handle the destruction of the object + /// + /// Is the GC disposing the object, or is it an explicit call ? + //////////////////////////////////////////////////////////// + protected override void Destroy(bool disposing) => sfSoundRecorder_destroy(CPointer); - [UnmanagedFunctionPointer(CallingConvention.Cdecl)] - private delegate bool ProcessCallback(IntPtr samples, UIntPtr nbSamples, IntPtr userData); + //////////////////////////////////////////////////////////// + /// + /// Function called directly by the C library ; convert + /// arguments and forward them to the internal virtual function + /// + /// User data -- unused + /// False to stop recording audio data, true to continue + //////////////////////////////////////////////////////////// + private bool StartRecording(IntPtr userData) => OnStart(); - [UnmanagedFunctionPointer(CallingConvention.Cdecl)] - private delegate void StopCallback(IntPtr userData); + //////////////////////////////////////////////////////////// + /// + /// Function called directly by the C library ; convert + /// arguments and forward them to the internal virtual function + /// + /// Pointer to the array of samples + /// Number of samples in the array + /// User data -- unused + /// False to stop recording audio data, true to continue + //////////////////////////////////////////////////////////// + private bool ProcessSamples(IntPtr samples, UIntPtr nbSamples, IntPtr userData) + { + var samplesArray = new short[(int)nbSamples]; + Marshal.Copy(samples, samplesArray, 0, samplesArray.Length); + + return OnProcessSamples(samplesArray); + } + + //////////////////////////////////////////////////////////// + /// + /// Function called directly by the C library ; convert + /// arguments and forward them to the internal virtual function + /// + /// User data -- unused + //////////////////////////////////////////////////////////// + private void StopRecording(IntPtr userData) => OnStop(); - private readonly StartCallback _startCallback; - private readonly ProcessCallback _processCallback; - private readonly StopCallback _stopCallback; + [UnmanagedFunctionPointer(CallingConvention.Cdecl)] + private delegate bool StartCallback(IntPtr userData); - #region Imports - [DllImport(CSFML.Audio, CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] - private static extern IntPtr sfSoundRecorder_create(StartCallback onStart, ProcessCallback onProcess, StopCallback onStop, IntPtr userData); + [UnmanagedFunctionPointer(CallingConvention.Cdecl)] + private delegate bool ProcessCallback(IntPtr samples, UIntPtr nbSamples, IntPtr userData); - [DllImport(CSFML.Audio, CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] - private static extern void sfSoundRecorder_destroy(IntPtr soundRecorder); + [UnmanagedFunctionPointer(CallingConvention.Cdecl)] + private delegate void StopCallback(IntPtr userData); - [DllImport(CSFML.Audio, CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] - [return: MarshalAs(UnmanagedType.I1)] - private static extern bool sfSoundRecorder_start(IntPtr soundRecorder, uint sampleRate); + private readonly StartCallback _startCallback; + private readonly ProcessCallback _processCallback; + private readonly StopCallback _stopCallback; - [DllImport(CSFML.Audio, CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] - private static extern void sfSoundRecorder_stop(IntPtr soundRecorder); + #region Imports + [DllImport(CSFML.Audio, CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] + private static extern IntPtr sfSoundRecorder_create(StartCallback onStart, ProcessCallback onProcess, StopCallback onStop, IntPtr userData); - [DllImport(CSFML.Audio, CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] - private static extern uint sfSoundRecorder_getSampleRate(IntPtr soundRecorder); + [DllImport(CSFML.Audio, CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] + private static extern void sfSoundRecorder_destroy(IntPtr soundRecorder); - [DllImport(CSFML.Audio, CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] - [return: MarshalAs(UnmanagedType.I1)] - private static extern bool sfSoundRecorder_isAvailable(); + [DllImport(CSFML.Audio, CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] + [return: MarshalAs(UnmanagedType.I1)] + private static extern bool sfSoundRecorder_start(IntPtr soundRecorder, uint sampleRate); - [DllImport(CSFML.Audio, CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] - private static extern unsafe IntPtr* sfSoundRecorder_getAvailableDevices(out UIntPtr count); + [DllImport(CSFML.Audio, CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] + private static extern void sfSoundRecorder_stop(IntPtr soundRecorder); - [DllImport(CSFML.Audio, CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] - private static extern IntPtr sfSoundRecorder_getDefaultDevice(); + [DllImport(CSFML.Audio, CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] + private static extern uint sfSoundRecorder_getSampleRate(IntPtr soundRecorder); - [DllImport(CSFML.Audio, CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] - [return: MarshalAs(UnmanagedType.I1)] - private static extern bool sfSoundRecorder_setDevice(IntPtr soundRecorder, string name); + [DllImport(CSFML.Audio, CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] + [return: MarshalAs(UnmanagedType.I1)] + private static extern bool sfSoundRecorder_isAvailable(); - [DllImport(CSFML.Audio, CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] - private static extern IntPtr sfSoundRecorder_getDevice(IntPtr soundRecorder); + [DllImport(CSFML.Audio, CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] + private static extern unsafe IntPtr* sfSoundRecorder_getAvailableDevices(out UIntPtr count); - [DllImport(CSFML.Audio, CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] - private static extern void sfSoundRecorder_setChannelCount(IntPtr soundRecorder, uint channelCount); + [DllImport(CSFML.Audio, CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] + private static extern IntPtr sfSoundRecorder_getDefaultDevice(); - [DllImport(CSFML.Audio, CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] - private static extern uint sfSoundRecorder_getChannelCount(IntPtr soundRecorder); + [DllImport(CSFML.Audio, CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] + [return: MarshalAs(UnmanagedType.I1)] + private static extern bool sfSoundRecorder_setDevice(IntPtr soundRecorder, string name); - [DllImport(CSFML.Audio, CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] - private static extern unsafe SoundChannel* sfSoundRecorder_getChannelMap(IntPtr soundRecorder, out UIntPtr count); - #endregion - } + [DllImport(CSFML.Audio, CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] + private static extern IntPtr sfSoundRecorder_getDevice(IntPtr soundRecorder); + + [DllImport(CSFML.Audio, CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] + private static extern void sfSoundRecorder_setChannelCount(IntPtr soundRecorder, uint channelCount); + + [DllImport(CSFML.Audio, CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] + private static extern uint sfSoundRecorder_getChannelCount(IntPtr soundRecorder); + + [DllImport(CSFML.Audio, CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] + private static extern unsafe SoundChannel* sfSoundRecorder_getChannelMap(IntPtr soundRecorder, out UIntPtr count); + #endregion } diff --git a/src/SFML.Audio/SoundStream.cs b/src/SFML.Audio/SoundStream.cs index 5698ee12..91d24509 100644 --- a/src/SFML.Audio/SoundStream.cs +++ b/src/SFML.Audio/SoundStream.cs @@ -3,702 +3,701 @@ using System.Security; using SFML.System; -namespace SFML.Audio +namespace SFML.Audio; + +//////////////////////////////////////////////////////////// +/// +/// Abstract base class for streamed audio sources +/// +//////////////////////////////////////////////////////////// +public abstract class SoundStream : ObjectBase { //////////////////////////////////////////////////////////// /// - /// Abstract base class for streamed audio sources + /// Default constructor /// //////////////////////////////////////////////////////////// - public abstract class SoundStream : ObjectBase + protected SoundStream() : + base(IntPtr.Zero) { - //////////////////////////////////////////////////////////// - /// - /// Default constructor - /// - //////////////////////////////////////////////////////////// - public SoundStream() : - base(IntPtr.Zero) - { - } + } + + //////////////////////////////////////////////////////////// + /// + /// 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 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 stream is played. + /// + //////////////////////////////////////////////////////////// + public void Play() => sfSoundStream_play(CPointer); + + //////////////////////////////////////////////////////////// + /// + /// Pause the audio stream. + /// + /// This function pauses the stream if it was playing, + /// otherwise (stream already paused or stopped) it has no effect. + /// + //////////////////////////////////////////////////////////// + public void Pause() => sfSoundStream_pause(CPointer); + + //////////////////////////////////////////////////////////// + /// + /// 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()). + /// + //////////////////////////////////////////////////////////// + public void Stop() => sfSoundStream_stop(CPointer); + + //////////////////////////////////////////////////////////// + /// + /// Sample rate of the stream + /// + /// The sample rate is the number of audio samples played per + /// second. The higher, the better the quality. + /// + //////////////////////////////////////////////////////////// + public uint SampleRate => sfSoundStream_getSampleRate(CPointer); - //////////////////////////////////////////////////////////// - /// - /// 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 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 stream is played. - /// - //////////////////////////////////////////////////////////// - public void Play() => sfSoundStream_play(CPointer); - - //////////////////////////////////////////////////////////// - /// - /// Pause the audio stream. - /// - /// This function pauses the stream if it was playing, - /// otherwise (stream already paused or stopped) it has no effect. - /// - //////////////////////////////////////////////////////////// - public void Pause() => sfSoundStream_pause(CPointer); - - //////////////////////////////////////////////////////////// - /// - /// 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()). - /// - //////////////////////////////////////////////////////////// - public void Stop() => sfSoundStream_stop(CPointer); - - //////////////////////////////////////////////////////////// - /// - /// Sample rate of the stream - /// - /// The sample rate is the number of audio samples played per - /// second. The higher, the better the quality. - /// - //////////////////////////////////////////////////////////// - public uint SampleRate => sfSoundStream_getSampleRate(CPointer); - - //////////////////////////////////////////////////////////// - /// - /// 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 spatialisation. - /// - //////////////////////////////////////////////////////////// - public SoundChannel[] ChannelMap + //////////////////////////////////////////////////////////// + /// + /// 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 spatialisation. + /// + //////////////////////////////////////////////////////////// + public SoundChannel[] ChannelMap + { + get { - get + unsafe { - unsafe - { - var channels = sfSoundStream_getChannelMap(CPointer, out var count); - var arr = new SoundChannel[(int)count]; + var channels = sfSoundStream_getChannelMap(CPointer, out var count); + var arr = new SoundChannel[(int)count]; - for (var i = 0; i < arr.Length; i++) - { - arr[i] = channels[i]; - } - - return arr; + for (var i = 0; i < arr.Length; i++) + { + arr[i] = channels[i]; } + + return arr; } } + } - //////////////////////////////////////////////////////////// - /// - /// Number of channels (1 = mono, 2 = stereo) - /// - //////////////////////////////////////////////////////////// - public uint ChannelCount => sfSoundStream_getChannelCount(CPointer); - - //////////////////////////////////////////////////////////// - /// - /// Current status of the sound stream (see SoundStatus enum) - /// - //////////////////////////////////////////////////////////// - public SoundStatus Status => sfSoundStream_getStatus(CPointer); - - //////////////////////////////////////////////////////////// - /// - /// Flag if the music should loop after reaching the end. - /// - /// If set, the music will restart from beginning after - /// reaching the end and so on, until it is stopped or - /// IsLooping = false is set. - /// The default looping state for music is false. - /// - //////////////////////////////////////////////////////////// - public bool IsLooping - { - get => sfSoundStream_isLooping(CPointer); - set => sfSoundStream_setLooping(CPointer, value); - } + //////////////////////////////////////////////////////////// + /// + /// Number of channels (1 = mono, 2 = stereo) + /// + //////////////////////////////////////////////////////////// + public uint ChannelCount => sfSoundStream_getChannelCount(CPointer); - //////////////////////////////////////////////////////////// - /// - /// Pitch of the stream. - /// - /// 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. - /// - //////////////////////////////////////////////////////////// - public float Pitch - { - get => sfSoundStream_getPitch(CPointer); - set => sfSoundStream_setPitch(CPointer, value); - } + //////////////////////////////////////////////////////////// + /// + /// Current status of the sound stream (see SoundStatus enum) + /// + //////////////////////////////////////////////////////////// + public SoundStatus Status => sfSoundStream_getStatus(CPointer); - //////////////////////////////////////////////////////////// - /// - /// 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. - /// - //////////////////////////////////////////////////////////// - public float Pan - { - get => sfSoundStream_getPan(CPointer); - set => sfSoundStream_setPan(CPointer, value); - } + //////////////////////////////////////////////////////////// + /// + /// Flag if the music should loop after reaching the end. + /// + /// If set, the music will restart from beginning after + /// reaching the end and so on, until it is stopped or + /// IsLooping = false is set. + /// The default looping state for music is false. + /// + //////////////////////////////////////////////////////////// + public bool IsLooping + { + get => sfSoundStream_isLooping(CPointer); + set => sfSoundStream_setLooping(CPointer, value); + } - //////////////////////////////////////////////////////////// - /// - /// Volume of the stream. - /// - /// The volume is a value between 0 (mute) and 100 (full volume). - /// The default value for the volume is 100. - /// - //////////////////////////////////////////////////////////// - public float Volume - { - get => sfSoundStream_getVolume(CPointer); - set => sfSoundStream_setVolume(CPointer, value); - } + //////////////////////////////////////////////////////////// + /// + /// Pitch of the stream. + /// + /// 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. + /// + //////////////////////////////////////////////////////////// + public float Pitch + { + get => sfSoundStream_getPitch(CPointer); + set => sfSoundStream_setPitch(CPointer, value); + } - //////////////////////////////////////////////////////////// - /// - /// Gets or sets 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. - /// - //////////////////////////////////////////////////////////// - public bool IsSpatializationEnabled - { - get => sfSoundStream_isSpatializationEnabled(CPointer); - set => sfSoundStream_setSpatializationEnabled(CPointer, value); - } + //////////////////////////////////////////////////////////// + /// + /// 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. + /// + //////////////////////////////////////////////////////////// + public float Pan + { + get => sfSoundStream_getPan(CPointer); + set => sfSoundStream_setPan(CPointer, value); + } - //////////////////////////////////////////////////////////// - /// - /// 3D position of the stream in the audio scene. - /// - /// Only sounds with one channel (mono sounds) can be - /// spatialized. - /// The default position of a sound is (0, 0, 0). - /// - //////////////////////////////////////////////////////////// - public Vector3f Position - { - get => sfSoundStream_getPosition(CPointer); - set => sfSoundStream_setPosition(CPointer, value); - } + //////////////////////////////////////////////////////////// + /// + /// Volume of the stream. + /// + /// The volume is a value between 0 (mute) and 100 (full volume). + /// The default value for the volume is 100. + /// + //////////////////////////////////////////////////////////// + public float Volume + { + get => sfSoundStream_getVolume(CPointer); + set => sfSoundStream_setVolume(CPointer, value); + } - //////////////////////////////////////////////////////////// - /// - /// 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). - /// - //////////////////////////////////////////////////////////// - public Vector3f Direction - { - get => sfSoundStream_getPosition(CPointer); - set => sfSoundStream_setPosition(CPointer, value); - } + //////////////////////////////////////////////////////////// + /// + /// Gets or sets 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. + /// + //////////////////////////////////////////////////////////// + public bool IsSpatializationEnabled + { + get => sfSoundStream_isSpatializationEnabled(CPointer); + set => sfSoundStream_setSpatializationEnabled(CPointer, value); + } - //////////////////////////////////////////////////////////// - /// - /// 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). - /// - //////////////////////////////////////////////////////////// - public Cone Cone - { - get => new Cone(sfSoundStream_getCone(CPointer)); - set => sfSoundStream_setCone(CPointer, value.Marshal()); - } + //////////////////////////////////////////////////////////// + /// + /// 3D position of the stream in the audio scene. + /// + /// Only sounds with one channel (mono sounds) can be + /// spatialized. + /// The default position of a sound is (0, 0, 0). + /// + //////////////////////////////////////////////////////////// + public Vector3f Position + { + get => sfSoundStream_getPosition(CPointer); + set => sfSoundStream_setPosition(CPointer, value); + } - //////////////////////////////////////////////////////////// - /// - /// 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. - /// - //////////////////////////////////////////////////////////// - public Vector3f Velocity - { - get => sfSoundStream_getVelocity(CPointer); - set => sfSoundStream_setVelocity(CPointer, value); - } + //////////////////////////////////////////////////////////// + /// + /// 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). + /// + //////////////////////////////////////////////////////////// + public Vector3f Direction + { + get => sfSoundStream_getPosition(CPointer); + set => sfSoundStream_setPosition(CPointer, value); + } - //////////////////////////////////////////////////////////// - /// - /// Doppler factor of the sound - /// - /// The doppler factor determines how strong the doppler - /// shift will be. - /// - //////////////////////////////////////////////////////////// - public float DopplerFactor - { - get => sfSoundStream_getDopplerFactor(CPointer); - set => sfSoundStream_setDopplerFactor(CPointer, value); - } + //////////////////////////////////////////////////////////// + /// + /// 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). + /// + //////////////////////////////////////////////////////////// + public Cone Cone + { + get => new(sfSoundStream_getCone(CPointer)); + set => sfSoundStream_setCone(CPointer, value.Marshal()); + } - //////////////////////////////////////////////////////////// - /// - /// 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. - /// - //////////////////////////////////////////////////////////// - public float DirectionalAttenuationFactor - { - get => sfSoundStream_getDirectionalAttenuationFactor(CPointer); - set => sfSoundStream_setDirectionalAttenuationFactor(CPointer, value); - } + //////////////////////////////////////////////////////////// + /// + /// 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. + /// + //////////////////////////////////////////////////////////// + public Vector3f Velocity + { + get => sfSoundStream_getVelocity(CPointer); + set => sfSoundStream_setVelocity(CPointer, value); + } - //////////////////////////////////////////////////////////// - /// - /// Make the stream'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 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). - /// - //////////////////////////////////////////////////////////// - public bool RelativeToListener - { - get => sfSoundStream_isRelativeToListener(CPointer); - set => sfSoundStream_setRelativeToListener(CPointer, value); - } + //////////////////////////////////////////////////////////// + /// + /// Doppler factor of the sound + /// + /// The doppler factor determines how strong the doppler + /// shift will be. + /// + //////////////////////////////////////////////////////////// + public float DopplerFactor + { + get => sfSoundStream_getDopplerFactor(CPointer); + set => sfSoundStream_setDopplerFactor(CPointer, value); + } - //////////////////////////////////////////////////////////// - /// - /// Minimum distance of the music. - /// - /// 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. - /// - //////////////////////////////////////////////////////////// - public float MinDistance - { - get => sfSoundStream_getMinDistance(CPointer); - set => sfSoundStream_setMinDistance(CPointer, value); - } + //////////////////////////////////////////////////////////// + /// + /// 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. + /// + //////////////////////////////////////////////////////////// + public float DirectionalAttenuationFactor + { + get => sfSoundStream_getDirectionalAttenuationFactor(CPointer); + set => sfSoundStream_setDirectionalAttenuationFactor(CPointer, value); + } - //////////////////////////////////////////////////////////// - /// - /// 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. - /// - //////////////////////////////////////////////////////////// - public float MaxDistance - { - get => sfSoundStream_getMaxDistance(CPointer); - set => sfSoundStream_setMaxDistance(CPointer, value); - } + //////////////////////////////////////////////////////////// + /// + /// Make the stream'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 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). + /// + //////////////////////////////////////////////////////////// + public bool RelativeToListener + { + get => sfSoundStream_isRelativeToListener(CPointer); + set => sfSoundStream_setRelativeToListener(CPointer, value); + } - //////////////////////////////////////////////////////////// - /// - /// 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. - /// - //////////////////////////////////////////////////////////// - public float MinGain - { - get => sfSoundStream_getMinGain(CPointer); - set => sfSoundStream_setMinGain(CPointer, value); - } + //////////////////////////////////////////////////////////// + /// + /// Minimum distance of the music. + /// + /// 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. + /// + //////////////////////////////////////////////////////////// + public float MinDistance + { + get => sfSoundStream_getMinDistance(CPointer); + set => sfSoundStream_setMinDistance(CPointer, value); + } - //////////////////////////////////////////////////////////// - /// - /// 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. - /// - //////////////////////////////////////////////////////////// - public float MaxGain - { - get => sfSoundStream_getMaxGain(CPointer); - set => sfSoundStream_setMaxGain(CPointer, value); - } + //////////////////////////////////////////////////////////// + /// + /// 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. + /// + //////////////////////////////////////////////////////////// + public float MaxDistance + { + get => sfSoundStream_getMaxDistance(CPointer); + set => sfSoundStream_setMaxDistance(CPointer, value); + } - //////////////////////////////////////////////////////////// - /// - /// Attenuation factor of the stream. - /// - /// The attenuation is a multiplicative factor which makes - /// the music 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. - /// - //////////////////////////////////////////////////////////// - public float Attenuation - { - get => sfSoundStream_getAttenuation(CPointer); - set => sfSoundStream_setAttenuation(CPointer, value); - } + //////////////////////////////////////////////////////////// + /// + /// 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. + /// + //////////////////////////////////////////////////////////// + public float MinGain + { + get => sfSoundStream_getMinGain(CPointer); + set => sfSoundStream_setMinGain(CPointer, value); + } - //////////////////////////////////////////////////////////// - /// - /// Current playing position of the stream. - /// - /// The playing position can be changed when the music is - /// either paused or playing. - /// - //////////////////////////////////////////////////////////// - public Time PlayingOffset - { - get => sfSoundStream_getPlayingOffset(CPointer); - set => sfSoundStream_setPlayingOffset(CPointer, value); - } + //////////////////////////////////////////////////////////// + /// + /// 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. + /// + //////////////////////////////////////////////////////////// + public float MaxGain + { + get => sfSoundStream_getMaxGain(CPointer); + set => sfSoundStream_setMaxGain(CPointer, value); + } + + //////////////////////////////////////////////////////////// + /// + /// Attenuation factor of the stream. + /// + /// The attenuation is a multiplicative factor which makes + /// the music 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. + /// + //////////////////////////////////////////////////////////// + public float Attenuation + { + get => sfSoundStream_getAttenuation(CPointer); + set => sfSoundStream_setAttenuation(CPointer, value); + } + + //////////////////////////////////////////////////////////// + /// + /// Current playing position of the stream. + /// + /// The playing position can be changed when the music is + /// either paused or playing. + /// + //////////////////////////////////////////////////////////// + public Time PlayingOffset + { + get => sfSoundStream_getPlayingOffset(CPointer); + set => sfSoundStream_setPlayingOffset(CPointer, value); + } - //////////////////////////////////////////////////////////// - /// - /// 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. - /// - /// The effect processor to attach to this sound, attach a null processor to disable processing - //////////////////////////////////////////////////////////// - public void SetEffectProcessor(EffectProcessor effectProcessor) + //////////////////////////////////////////////////////////// + /// + /// 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. + /// + /// The effect processor to attach to this sound, attach a null processor to disable processing + //////////////////////////////////////////////////////////// + public void SetEffectProcessor(EffectProcessor effectProcessor) + { + _effectProcessor = (inputFrames, inputFrameCount, outputFrames, outputFrameCount, frameChannelCount) => { - _effectProcessor = (inputFrames, inputFrameCount, outputFrames, outputFrameCount, frameChannelCount) => - { - var inputFramesArray = new float[inputFrameCount]; - var outputFramesArray = new float[outputFrameCount]; + var inputFramesArray = new float[inputFrameCount]; + var outputFramesArray = new float[outputFrameCount]; - Marshal.Copy(inputFrames, inputFramesArray, 0, inputFramesArray.Length); - var written = effectProcessor(inputFramesArray, outputFramesArray, frameChannelCount); - Marshal.Copy(outputFramesArray, 0, outputFrames, outputFramesArray.Length); + Marshal.Copy(inputFrames, inputFramesArray, 0, inputFramesArray.Length); + var written = effectProcessor(inputFramesArray, outputFramesArray, frameChannelCount); + Marshal.Copy(outputFramesArray, 0, outputFrames, outputFramesArray.Length); - return written; - }; + return written; + }; + + sfSoundStream_setEffectProcessor(CPointer, Marshal.GetFunctionPointerForDelegate(_effectProcessor)); + } - sfSoundStream_setEffectProcessor(CPointer, Marshal.GetFunctionPointerForDelegate(_effectProcessor)); + //////////////////////////////////////////////////////////// + /// + /// Provide a string describing the object + /// + /// String description of the object + //////////////////////////////////////////////////////////// + public override string ToString() + { + if (IsInvalid) + { + return MakeDisposedObjectString(); } - //////////////////////////////////////////////////////////// - /// - /// Provide a string describing the object - /// - /// String description of the object - //////////////////////////////////////////////////////////// - public override string ToString() + return "[SoundStream]" + + " SampleRate(" + SampleRate + ")" + + " ChannelCount(" + ChannelCount + ")" + + " Status(" + Status + ")" + + " IsLooping(" + IsLooping + ")" + + " Pitch(" + Pitch + ")" + + " Volume(" + Volume + ")" + + " Position(" + Position + ")" + + " RelativeToListener(" + RelativeToListener + ")" + + " MinDistance(" + MinDistance + ")" + + " Attenuation(" + Attenuation + ")" + + " PlayingOffset(" + PlayingOffset + ")"; + } + + //////////////////////////////////////////////////////////// + /// + /// Set the audio stream parameters, you must call it before Play() + /// + /// Number of channels + /// Sample rate, in samples per second + /// Map of position in sample frame to sound channel + //////////////////////////////////////////////////////////// + protected void Initialize(uint channelCount, uint sampleRate, SoundChannel[] channelMapData) + { + _getDataCallback = new GetDataCallbackType(GetData); + _seekCallback = new SeekCallbackType(Seek); + + unsafe { - if (IsInvalid) + fixed (SoundChannel* data = channelMapData) { - return MakeDisposedObjectString(); + CPointer = sfSoundStream_create(_getDataCallback, _seekCallback, channelCount, sampleRate, data, (UIntPtr)channelMapData.Length, IntPtr.Zero); } - - return "[SoundStream]" + - " SampleRate(" + SampleRate + ")" + - " ChannelCount(" + ChannelCount + ")" + - " Status(" + Status + ")" + - " IsLooping(" + IsLooping + ")" + - " Pitch(" + Pitch + ")" + - " Volume(" + Volume + ")" + - " Position(" + Position + ")" + - " RelativeToListener(" + RelativeToListener + ")" + - " MinDistance(" + MinDistance + ")" + - " Attenuation(" + Attenuation + ")" + - " PlayingOffset(" + PlayingOffset + ")"; } + } - //////////////////////////////////////////////////////////// - /// - /// Set the audio stream parameters, you must call it before Play() - /// - /// Number of channels - /// Sample rate, in samples per second - /// Map of position in sample frame to sound channel - //////////////////////////////////////////////////////////// - protected void Initialize(uint channelCount, uint sampleRate, SoundChannel[] channelMapData) - { - _getDataCallback = new GetDataCallbackType(GetData); - _seekCallback = new SeekCallbackType(Seek); + //////////////////////////////////////////////////////////// + /// + /// Virtual function called each time new audio data is needed to feed the stream + /// + /// Array of samples to fill for the stream + /// True to continue playback, false to stop + //////////////////////////////////////////////////////////// + protected abstract bool OnGetData(out short[] samples); + + //////////////////////////////////////////////////////////// + /// + /// Virtual function called to seek into the stream + /// + /// New position + //////////////////////////////////////////////////////////// + protected abstract void OnSeek(Time timeOffset); + + //////////////////////////////////////////////////////////// + /// + /// Handle the destruction of the object + /// + /// Is the GC disposing the object, or is it an explicit call ? + //////////////////////////////////////////////////////////// + protected override void Destroy(bool disposing) => sfSoundStream_destroy(CPointer); + + //////////////////////////////////////////////////////////// + /// + /// Structure mapping the C library arguments passed to the data callback + /// + //////////////////////////////////////////////////////////// + [StructLayout(LayoutKind.Sequential)] + private struct Chunk + { + public unsafe short* Samples; + public uint SampleCount; + } + //////////////////////////////////////////////////////////// + /// + /// Called each time new audio data is needed to feed the stream + /// + /// Data chunk to fill with new audio samples + /// User data -- unused + /// True to continue playback, false to stop + //////////////////////////////////////////////////////////// + private bool GetData(ref Chunk dataChunk, IntPtr userData) + { + if (OnGetData(out _tempBuffer)) + { unsafe { - fixed (SoundChannel* data = channelMapData) + fixed (short* samplesPtr = _tempBuffer) { - CPointer = sfSoundStream_create(_getDataCallback, _seekCallback, channelCount, sampleRate, data, (UIntPtr)channelMapData.Length, IntPtr.Zero); + dataChunk.Samples = samplesPtr; + dataChunk.SampleCount = (uint)_tempBuffer.Length; } } - } - //////////////////////////////////////////////////////////// - /// - /// Virtual function called each time new audio data is needed to feed the stream - /// - /// Array of samples to fill for the stream - /// True to continue playback, false to stop - //////////////////////////////////////////////////////////// - protected abstract bool OnGetData(out short[] samples); - - //////////////////////////////////////////////////////////// - /// - /// Virtual function called to seek into the stream - /// - /// New position - //////////////////////////////////////////////////////////// - protected abstract void OnSeek(Time timeOffset); - - //////////////////////////////////////////////////////////// - /// - /// Handle the destruction of the object - /// - /// Is the GC disposing the object, or is it an explicit call ? - //////////////////////////////////////////////////////////// - protected override void Destroy(bool disposing) => sfSoundStream_destroy(CPointer); - - //////////////////////////////////////////////////////////// - /// - /// Structure mapping the C library arguments passed to the data callback - /// - //////////////////////////////////////////////////////////// - [StructLayout(LayoutKind.Sequential)] - private struct Chunk - { - public unsafe short* Samples; - public uint SampleCount; + return true; } - - //////////////////////////////////////////////////////////// - /// - /// Called each time new audio data is needed to feed the stream - /// - /// Data chunk to fill with new audio samples - /// User data -- unused - /// True to continue playback, false to stop - //////////////////////////////////////////////////////////// - private bool GetData(ref Chunk dataChunk, IntPtr userData) + else { - if (OnGetData(out _tempBuffer)) - { - unsafe - { - fixed (short* samplesPtr = _tempBuffer) - { - dataChunk.Samples = samplesPtr; - dataChunk.SampleCount = (uint)_tempBuffer.Length; - } - } - - return true; - } - else - { - return false; - } + return false; } + } - //////////////////////////////////////////////////////////// - /// - /// Called to seek in the stream - /// - /// New position - /// User data -- unused - /// If false is returned, the playback is aborted - //////////////////////////////////////////////////////////// - private void Seek(Time timeOffset, IntPtr userData) => OnSeek(timeOffset); + //////////////////////////////////////////////////////////// + /// + /// Called to seek in the stream + /// + /// New position + /// User data -- unused + /// If false is returned, the playback is aborted + //////////////////////////////////////////////////////////// + private void Seek(Time timeOffset, IntPtr userData) => OnSeek(timeOffset); - [UnmanagedFunctionPointer(CallingConvention.Cdecl)] - private delegate bool GetDataCallbackType(ref Chunk dataChunk, IntPtr userData); + [UnmanagedFunctionPointer(CallingConvention.Cdecl)] + private delegate bool GetDataCallbackType(ref Chunk dataChunk, IntPtr userData); - [UnmanagedFunctionPointer(CallingConvention.Cdecl)] - private delegate void SeekCallbackType(Time timeOffset, IntPtr userData); + [UnmanagedFunctionPointer(CallingConvention.Cdecl)] + private delegate void SeekCallbackType(Time timeOffset, IntPtr userData); - private GetDataCallbackType _getDataCallback; - private SeekCallbackType _seekCallback; - private EffectProcessorInternal _effectProcessor; - private short[] _tempBuffer; + private GetDataCallbackType _getDataCallback; + private SeekCallbackType _seekCallback; + private EffectProcessorInternal _effectProcessor; + private short[] _tempBuffer; - #region Imports - [DllImport(CSFML.Audio, CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] - private static extern unsafe IntPtr sfSoundStream_create(GetDataCallbackType onGetData, SeekCallbackType onSeek, uint channelCount, uint sampleRate, SoundChannel* channelMapData, UIntPtr channelMapSize, IntPtr userData); + #region Imports + [DllImport(CSFML.Audio, CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] + private static extern unsafe IntPtr sfSoundStream_create(GetDataCallbackType onGetData, SeekCallbackType onSeek, uint channelCount, uint sampleRate, SoundChannel* channelMapData, UIntPtr channelMapSize, IntPtr userData); - [DllImport(CSFML.Audio, CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] - private static extern void sfSoundStream_destroy(IntPtr soundStream); + [DllImport(CSFML.Audio, CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] + private static extern void sfSoundStream_destroy(IntPtr soundStream); - [DllImport(CSFML.Audio, CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] - private static extern void sfSoundStream_play(IntPtr soundStream); + [DllImport(CSFML.Audio, CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] + private static extern void sfSoundStream_play(IntPtr soundStream); - [DllImport(CSFML.Audio, CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] - private static extern void sfSoundStream_pause(IntPtr soundStream); + [DllImport(CSFML.Audio, CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] + private static extern void sfSoundStream_pause(IntPtr soundStream); - [DllImport(CSFML.Audio, CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] - private static extern void sfSoundStream_stop(IntPtr soundStream); + [DllImport(CSFML.Audio, CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] + private static extern void sfSoundStream_stop(IntPtr soundStream); - [DllImport(CSFML.Audio, CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] - private static extern SoundStatus sfSoundStream_getStatus(IntPtr soundStream); + [DllImport(CSFML.Audio, CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] + private static extern SoundStatus sfSoundStream_getStatus(IntPtr soundStream); - [DllImport(CSFML.Audio, CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] - private static extern uint sfSoundStream_getChannelCount(IntPtr soundStream); + [DllImport(CSFML.Audio, CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] + private static extern uint sfSoundStream_getChannelCount(IntPtr soundStream); - [DllImport(CSFML.Audio, CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] - private static extern uint sfSoundStream_getSampleRate(IntPtr soundStream); + [DllImport(CSFML.Audio, CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] + private static extern uint sfSoundStream_getSampleRate(IntPtr soundStream); - [DllImport(CSFML.Audio, CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] - private static extern unsafe SoundChannel* sfSoundStream_getChannelMap(IntPtr soundStream, out UIntPtr count); + [DllImport(CSFML.Audio, CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] + private static extern unsafe SoundChannel* sfSoundStream_getChannelMap(IntPtr soundStream, out UIntPtr count); - [DllImport(CSFML.Audio, CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] - private static extern void sfSoundStream_setPitch(IntPtr soundStream, float pitch); + [DllImport(CSFML.Audio, CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] + private static extern void sfSoundStream_setPitch(IntPtr soundStream, float pitch); - [DllImport(CSFML.Audio, CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] - private static extern void sfSoundStream_setPan(IntPtr soundStream, float pan); + [DllImport(CSFML.Audio, CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] + private static extern void sfSoundStream_setPan(IntPtr soundStream, float pan); - [DllImport(CSFML.Audio, CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] - private static extern void sfSoundStream_setVolume(IntPtr soundStream, float volume); + [DllImport(CSFML.Audio, CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] + private static extern void sfSoundStream_setVolume(IntPtr soundStream, float volume); - [DllImport(CSFML.Audio, CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] - private static extern void sfSoundStream_setSpatializationEnabled(IntPtr soundStream, bool enabled); + [DllImport(CSFML.Audio, CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] + private static extern void sfSoundStream_setSpatializationEnabled(IntPtr soundStream, bool enabled); - [DllImport(CSFML.Audio, CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] - private static extern void sfSoundStream_setPosition(IntPtr soundStream, Vector3f position); + [DllImport(CSFML.Audio, CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] + private static extern void sfSoundStream_setPosition(IntPtr soundStream, Vector3f position); - [DllImport(CSFML.Audio, CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] - private static extern void sfSoundStream_setDirection(IntPtr soundStream, Vector3f direction); + [DllImport(CSFML.Audio, CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] + private static extern void sfSoundStream_setDirection(IntPtr soundStream, Vector3f direction); - [DllImport(CSFML.Audio, CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] - private static extern void sfSoundStream_setCone(IntPtr soundStream, Cone.MarshalData cone); + [DllImport(CSFML.Audio, CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] + private static extern void sfSoundStream_setCone(IntPtr soundStream, Cone.MarshalData cone); - [DllImport(CSFML.Audio, CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] - private static extern void sfSoundStream_setVelocity(IntPtr soundStream, Vector3f velocity); + [DllImport(CSFML.Audio, CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] + private static extern void sfSoundStream_setVelocity(IntPtr soundStream, Vector3f velocity); - [DllImport(CSFML.Audio, CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] - private static extern void sfSoundStream_setDopplerFactor(IntPtr soundStream, float factor); + [DllImport(CSFML.Audio, CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] + private static extern void sfSoundStream_setDopplerFactor(IntPtr soundStream, float factor); - [DllImport(CSFML.Audio, CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] - private static extern void sfSoundStream_setDirectionalAttenuationFactor(IntPtr soundStream, float factor); + [DllImport(CSFML.Audio, CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] + private static extern void sfSoundStream_setDirectionalAttenuationFactor(IntPtr soundStream, float factor); - [DllImport(CSFML.Audio, CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] - private static extern void sfSoundStream_setRelativeToListener(IntPtr soundStream, bool relative); + [DllImport(CSFML.Audio, CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] + private static extern void sfSoundStream_setRelativeToListener(IntPtr soundStream, bool relative); - [DllImport(CSFML.Audio, CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] - private static extern void sfSoundStream_setMinDistance(IntPtr soundStream, float minDistance); + [DllImport(CSFML.Audio, CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] + private static extern void sfSoundStream_setMinDistance(IntPtr soundStream, float minDistance); - [DllImport(CSFML.Audio, CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] - private static extern void sfSoundStream_setMaxDistance(IntPtr soundStream, float maxDistance); + [DllImport(CSFML.Audio, CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] + private static extern void sfSoundStream_setMaxDistance(IntPtr soundStream, float maxDistance); - [DllImport(CSFML.Audio, CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] - private static extern void sfSoundStream_setMinGain(IntPtr soundStream, float gain); + [DllImport(CSFML.Audio, CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] + private static extern void sfSoundStream_setMinGain(IntPtr soundStream, float gain); - [DllImport(CSFML.Audio, CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] - private static extern void sfSoundStream_setMaxGain(IntPtr soundStream, float gain); + [DllImport(CSFML.Audio, CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] + private static extern void sfSoundStream_setMaxGain(IntPtr soundStream, float gain); - [DllImport(CSFML.Audio, CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] - private static extern void sfSoundStream_setAttenuation(IntPtr soundStream, float attenuation); + [DllImport(CSFML.Audio, CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] + private static extern void sfSoundStream_setAttenuation(IntPtr soundStream, float attenuation); - [DllImport(CSFML.Audio, CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] - private static extern void sfSoundStream_setPlayingOffset(IntPtr soundStream, Time timeOffset); + [DllImport(CSFML.Audio, CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] + private static extern void sfSoundStream_setPlayingOffset(IntPtr soundStream, Time timeOffset); - [DllImport(CSFML.Audio, CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] - private static extern void sfSoundStream_setLooping(IntPtr soundStream, bool loop); + [DllImport(CSFML.Audio, CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] + private static extern void sfSoundStream_setLooping(IntPtr soundStream, bool loop); - [DllImport(CSFML.Audio, CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] - private static extern float sfSoundStream_getPitch(IntPtr soundStream); + [DllImport(CSFML.Audio, CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] + private static extern float sfSoundStream_getPitch(IntPtr soundStream); - [DllImport(CSFML.Audio, CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] - private static extern float sfSoundStream_getPan(IntPtr soundStream); + [DllImport(CSFML.Audio, CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] + private static extern float sfSoundStream_getPan(IntPtr soundStream); - [DllImport(CSFML.Audio, CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] - private static extern float sfSoundStream_getVolume(IntPtr soundStream); + [DllImport(CSFML.Audio, CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] + private static extern float sfSoundStream_getVolume(IntPtr soundStream); - [DllImport(CSFML.Audio, CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] - [return: MarshalAs(UnmanagedType.I1)] - private static extern bool sfSoundStream_isSpatializationEnabled(IntPtr soundStream); + [DllImport(CSFML.Audio, CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] + [return: MarshalAs(UnmanagedType.I1)] + private static extern bool sfSoundStream_isSpatializationEnabled(IntPtr soundStream); - [DllImport(CSFML.Audio, CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] - private static extern Vector3f sfSoundStream_getPosition(IntPtr soundStream); + [DllImport(CSFML.Audio, CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] + private static extern Vector3f sfSoundStream_getPosition(IntPtr soundStream); - [DllImport(CSFML.Audio, CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] - private static extern Vector3f sfSoundStream_getDirection(IntPtr soundStream); + [DllImport(CSFML.Audio, CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] + private static extern Vector3f sfSoundStream_getDirection(IntPtr soundStream); - [DllImport(CSFML.Audio, CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] - private static extern Cone.MarshalData sfSoundStream_getCone(IntPtr soundStream); + [DllImport(CSFML.Audio, CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] + private static extern Cone.MarshalData sfSoundStream_getCone(IntPtr soundStream); - [DllImport(CSFML.Audio, CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] - private static extern Vector3f sfSoundStream_getVelocity(IntPtr soundStream); + [DllImport(CSFML.Audio, CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] + private static extern Vector3f sfSoundStream_getVelocity(IntPtr soundStream); - [DllImport(CSFML.Audio, CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] - private static extern float sfSoundStream_getDopplerFactor(IntPtr soundStream); + [DllImport(CSFML.Audio, CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] + private static extern float sfSoundStream_getDopplerFactor(IntPtr soundStream); - [DllImport(CSFML.Audio, CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] - private static extern float sfSoundStream_getDirectionalAttenuationFactor(IntPtr soundStream); + [DllImport(CSFML.Audio, CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] + private static extern float sfSoundStream_getDirectionalAttenuationFactor(IntPtr soundStream); - [DllImport(CSFML.Audio, CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] - [return: MarshalAs(UnmanagedType.I1)] - private static extern bool sfSoundStream_isRelativeToListener(IntPtr soundStream); + [DllImport(CSFML.Audio, CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] + [return: MarshalAs(UnmanagedType.I1)] + private static extern bool sfSoundStream_isRelativeToListener(IntPtr soundStream); - [DllImport(CSFML.Audio, CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] - private static extern float sfSoundStream_getMinDistance(IntPtr soundStream); + [DllImport(CSFML.Audio, CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] + private static extern float sfSoundStream_getMinDistance(IntPtr soundStream); - [DllImport(CSFML.Audio, CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] - private static extern float sfSoundStream_getMaxDistance(IntPtr soundStream); + [DllImport(CSFML.Audio, CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] + private static extern float sfSoundStream_getMaxDistance(IntPtr soundStream); - [DllImport(CSFML.Audio, CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] - private static extern float sfSoundStream_getMinGain(IntPtr soundStream); + [DllImport(CSFML.Audio, CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] + private static extern float sfSoundStream_getMinGain(IntPtr soundStream); - [DllImport(CSFML.Audio, CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] - private static extern float sfSoundStream_getMaxGain(IntPtr soundStream); + [DllImport(CSFML.Audio, CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] + private static extern float sfSoundStream_getMaxGain(IntPtr soundStream); - [DllImport(CSFML.Audio, CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] - private static extern float sfSoundStream_getAttenuation(IntPtr soundStream); + [DllImport(CSFML.Audio, CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] + private static extern float sfSoundStream_getAttenuation(IntPtr soundStream); - [DllImport(CSFML.Audio, CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] - [return: MarshalAs(UnmanagedType.I1)] - private static extern bool sfSoundStream_isLooping(IntPtr soundStream); + [DllImport(CSFML.Audio, CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] + [return: MarshalAs(UnmanagedType.I1)] + private static extern bool sfSoundStream_isLooping(IntPtr soundStream); - [DllImport(CSFML.Audio, CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] - private static extern void sfSoundStream_setEffectProcessor(IntPtr soundStream, IntPtr effectProcessor); + [DllImport(CSFML.Audio, CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] + private static extern void sfSoundStream_setEffectProcessor(IntPtr soundStream, IntPtr effectProcessor); - [DllImport(CSFML.Audio, CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] - private static extern Time sfSoundStream_getPlayingOffset(IntPtr soundStream); - #endregion - } + [DllImport(CSFML.Audio, CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] + private static extern Time sfSoundStream_getPlayingOffset(IntPtr soundStream); + #endregion } diff --git a/src/SFML.Graphics/BlendMode.cs b/src/SFML.Graphics/BlendMode.cs index 5c100ee3..ccab530d 100644 --- a/src/SFML.Graphics/BlendMode.cs +++ b/src/SFML.Graphics/BlendMode.cs @@ -1,211 +1,210 @@ using System; using System.Runtime.InteropServices; -namespace SFML.Graphics +namespace SFML.Graphics; + +//////////////////////////////////////////////////////////// +/// +/// Blending modes for drawing +/// +//////////////////////////////////////////////////////////// +[StructLayout(LayoutKind.Sequential)] +public struct BlendMode : IEquatable { //////////////////////////////////////////////////////////// /// - /// Blending modes for drawing + /// Enumeration of the blending factors /// //////////////////////////////////////////////////////////// - [StructLayout(LayoutKind.Sequential)] - public struct BlendMode : IEquatable + public enum Factor { - //////////////////////////////////////////////////////////// - /// - /// Enumeration of the blending factors - /// - //////////////////////////////////////////////////////////// - public enum Factor - { - /// (0, 0, 0, 0) - Zero, - - /// (1, 1, 1, 1) - One, - - /// (src.r, src.g, src.b, src.a) - SrcColor, - - /// (1, 1, 1, 1) - (src.r, src.g, src.b, src.a) - OneMinusSrcColor, - - /// (dst.r, dst.g, dst.b, dst.a) - DstColor, - - /// (1, 1, 1, 1) - (dst.r, dst.g, dst.b, dst.a) - OneMinusDstColor, - - /// (src.a, src.a, src.a, src.a) - SrcAlpha, - - /// (1, 1, 1, 1) - (src.a, src.a, src.a, src.a) - OneMinusSrcAlpha, - - /// (dst.a, dst.a, dst.a, dst.a) - DstAlpha, - - /// (1, 1, 1, 1) - (dst.a, dst.a, dst.a, dst.a) - OneMinusDstAlpha - } - - //////////////////////////////////////////////////////////// - /// - /// Enumeration of the blending equations - /// - //////////////////////////////////////////////////////////// - public enum Equation - { - /// Pixel = Src * SrcFactor + Dst * DstFactor - Add, - - /// Pixel = Src * SrcFactor - Dst * DstFactor - Subtract, - - /// Pixel = Dst * DstFactor - Src * SrcFactor - ReverseSubtract, - - /// Pixel = min(Dst, Src) - Min, - - /// Pixel = max(Dst, Src) - Max - } - - /// Blend source and dest according to dest alpha - public static readonly BlendMode Alpha = new BlendMode(Factor.SrcAlpha, Factor.OneMinusSrcAlpha, Equation.Add, - Factor.One, Factor.OneMinusSrcAlpha, Equation.Add); - - /// Add source to dest - public static readonly BlendMode Add = new BlendMode(Factor.SrcAlpha, Factor.One, Equation.Add, - Factor.One, Factor.One, Equation.Add); - - /// Multiply source and dest - public static readonly BlendMode Multiply = new BlendMode(Factor.DstColor, Factor.Zero); - - /// Take minimum between source and dest - public static readonly BlendMode Min = new BlendMode(Factor.One, Factor.One, Equation.Min); - - /// Take maximum between source and dest - public static readonly BlendMode Max = new BlendMode(Factor.One, Factor.One, Equation.Max); - - /// Overwrite dest with source - public static readonly BlendMode None = new BlendMode(Factor.One, Factor.Zero); - - //////////////////////////////////////////////////////////// - /// - /// Construct the blend mode given the factors and equation - /// - /// Specifies how to compute the source factor for the color and alpha channels. - /// Specifies how to compute the destination factor for the color and alpha channels. - //////////////////////////////////////////////////////////// - public BlendMode(Factor sourceFactor, Factor destinationFactor) - : this(sourceFactor, destinationFactor, Equation.Add) - { - } - - //////////////////////////////////////////////////////////// - /// - /// Construct the blend mode given the factors and equation - /// - /// Specifies how to compute the source factor for the color and alpha channels. - /// Specifies how to compute the destination factor for the color and alpha channels. - /// Specifies how to combine the source and destination colors and alpha. - //////////////////////////////////////////////////////////// - public BlendMode(Factor sourceFactor, Factor destinationFactor, Equation blendEquation) - : this(sourceFactor, destinationFactor, blendEquation, sourceFactor, destinationFactor, blendEquation) - { - } - - //////////////////////////////////////////////////////////// - /// - /// Construct the blend mode given the factors and equation - /// - /// Specifies how to compute the source factor for the color channels. - /// Specifies how to compute the destination factor for the color channels. - /// Specifies how to combine the source and destination colors. - /// Specifies how to compute the source factor. - /// Specifies how to compute the destination factor. - /// Specifies how to combine the source and destination alphas. - //////////////////////////////////////////////////////////// - public BlendMode(Factor colorSourceFactor, Factor colorDestinationFactor, Equation colorBlendEquation, Factor alphaSourceFactor, Factor alphaDestinationFactor, Equation alphaBlendEquation) - { - ColorSrcFactor = colorSourceFactor; - ColorDstFactor = colorDestinationFactor; - ColorEquation = colorBlendEquation; - AlphaSrcFactor = alphaSourceFactor; - AlphaDstFactor = alphaDestinationFactor; - AlphaEquation = alphaBlendEquation; - } - - //////////////////////////////////////////////////////////// - /// - /// Compare two blend modes and checks if they are equal - /// - /// Blend Modes are equal - //////////////////////////////////////////////////////////// - public static bool operator ==(BlendMode left, BlendMode right) => left.Equals(right); - - //////////////////////////////////////////////////////////// - /// - /// Compare two blend modes and checks if they are not equal - /// - /// Blend Modes are not equal - //////////////////////////////////////////////////////////// - public static bool operator !=(BlendMode left, BlendMode right) => !left.Equals(right); - - //////////////////////////////////////////////////////////// - /// - /// Compare blend mode and object and checks if they are equal - /// - /// Object to check - /// Object and blend mode are equal - //////////////////////////////////////////////////////////// - public override bool Equals(object obj) => (obj is BlendMode mode) && Equals(mode); - - /////////////////////////////////////////////////////////// - /// - /// Compare two blend modes and checks if they are equal - /// - /// Blend Mode to check - /// blend modes are equal - //////////////////////////////////////////////////////////// - public bool Equals(BlendMode other) => (ColorSrcFactor == other.ColorSrcFactor) && - (ColorDstFactor == other.ColorDstFactor) && - (ColorEquation == other.ColorEquation) && - (AlphaSrcFactor == other.AlphaSrcFactor) && - (AlphaDstFactor == other.AlphaDstFactor) && - (AlphaEquation == other.AlphaEquation); - - //////////////////////////////////////////////////////////// - /// - /// Provide a integer describing the object - /// - /// Integer description of the object - //////////////////////////////////////////////////////////// - public override int GetHashCode() => ColorSrcFactor.GetHashCode() ^ - ColorDstFactor.GetHashCode() ^ - ColorEquation.GetHashCode() ^ - AlphaSrcFactor.GetHashCode() ^ - AlphaDstFactor.GetHashCode() ^ - AlphaEquation.GetHashCode(); - - /// Source blending factor for the color channels - public Factor ColorSrcFactor; - - /// Destination blending factor for the color channels - public Factor ColorDstFactor; - - /// Blending equation for the color channels - public Equation ColorEquation; - - /// Source blending factor for the alpha channel - public Factor AlphaSrcFactor; - - /// Destination blending factor for the alpha channel - public Factor AlphaDstFactor; - - /// Blending equation for the alpha channel - public Equation AlphaEquation; + /// (0, 0, 0, 0) + Zero, + + /// (1, 1, 1, 1) + One, + + /// (src.r, src.g, src.b, src.a) + SrcColor, + + /// (1, 1, 1, 1) - (src.r, src.g, src.b, src.a) + OneMinusSrcColor, + + /// (dst.r, dst.g, dst.b, dst.a) + DstColor, + + /// (1, 1, 1, 1) - (dst.r, dst.g, dst.b, dst.a) + OneMinusDstColor, + + /// (src.a, src.a, src.a, src.a) + SrcAlpha, + + /// (1, 1, 1, 1) - (src.a, src.a, src.a, src.a) + OneMinusSrcAlpha, + + /// (dst.a, dst.a, dst.a, dst.a) + DstAlpha, + + /// (1, 1, 1, 1) - (dst.a, dst.a, dst.a, dst.a) + OneMinusDstAlpha + } + + //////////////////////////////////////////////////////////// + /// + /// Enumeration of the blending equations + /// + //////////////////////////////////////////////////////////// + public enum Equation + { + /// Pixel = Src * SrcFactor + Dst * DstFactor + Add, + + /// Pixel = Src * SrcFactor - Dst * DstFactor + Subtract, + + /// Pixel = Dst * DstFactor - Src * SrcFactor + ReverseSubtract, + + /// Pixel = min(Dst, Src) + Min, + + /// Pixel = max(Dst, Src) + Max } + + /// Blend source and dest according to dest alpha + public static readonly BlendMode Alpha = new(Factor.SrcAlpha, Factor.OneMinusSrcAlpha, Equation.Add, + Factor.One, Factor.OneMinusSrcAlpha, Equation.Add); + + /// Add source to dest + public static readonly BlendMode Add = new(Factor.SrcAlpha, Factor.One, Equation.Add, + Factor.One, Factor.One, Equation.Add); + + /// Multiply source and dest + public static readonly BlendMode Multiply = new(Factor.DstColor, Factor.Zero); + + /// Take minimum between source and dest + public static readonly BlendMode Min = new(Factor.One, Factor.One, Equation.Min); + + /// Take maximum between source and dest + public static readonly BlendMode Max = new(Factor.One, Factor.One, Equation.Max); + + /// Overwrite dest with source + public static readonly BlendMode None = new(Factor.One, Factor.Zero); + + //////////////////////////////////////////////////////////// + /// + /// Construct the blend mode given the factors and equation + /// + /// Specifies how to compute the source factor for the color and alpha channels. + /// Specifies how to compute the destination factor for the color and alpha channels. + //////////////////////////////////////////////////////////// + public BlendMode(Factor sourceFactor, Factor destinationFactor) + : this(sourceFactor, destinationFactor, Equation.Add) + { + } + + //////////////////////////////////////////////////////////// + /// + /// Construct the blend mode given the factors and equation + /// + /// Specifies how to compute the source factor for the color and alpha channels. + /// Specifies how to compute the destination factor for the color and alpha channels. + /// Specifies how to combine the source and destination colors and alpha. + //////////////////////////////////////////////////////////// + public BlendMode(Factor sourceFactor, Factor destinationFactor, Equation blendEquation) + : this(sourceFactor, destinationFactor, blendEquation, sourceFactor, destinationFactor, blendEquation) + { + } + + //////////////////////////////////////////////////////////// + /// + /// Construct the blend mode given the factors and equation + /// + /// Specifies how to compute the source factor for the color channels. + /// Specifies how to compute the destination factor for the color channels. + /// Specifies how to combine the source and destination colors. + /// Specifies how to compute the source factor. + /// Specifies how to compute the destination factor. + /// Specifies how to combine the source and destination alphas. + //////////////////////////////////////////////////////////// + public BlendMode(Factor colorSourceFactor, Factor colorDestinationFactor, Equation colorBlendEquation, Factor alphaSourceFactor, Factor alphaDestinationFactor, Equation alphaBlendEquation) + { + ColorSrcFactor = colorSourceFactor; + ColorDstFactor = colorDestinationFactor; + ColorEquation = colorBlendEquation; + AlphaSrcFactor = alphaSourceFactor; + AlphaDstFactor = alphaDestinationFactor; + AlphaEquation = alphaBlendEquation; + } + + //////////////////////////////////////////////////////////// + /// + /// Compare two blend modes and checks if they are equal + /// + /// Blend Modes are equal + //////////////////////////////////////////////////////////// + public static bool operator ==(BlendMode left, BlendMode right) => left.Equals(right); + + //////////////////////////////////////////////////////////// + /// + /// Compare two blend modes and checks if they are not equal + /// + /// Blend Modes are not equal + //////////////////////////////////////////////////////////// + public static bool operator !=(BlendMode left, BlendMode right) => !left.Equals(right); + + //////////////////////////////////////////////////////////// + /// + /// Compare blend mode and object and checks if they are equal + /// + /// Object to check + /// Object and blend mode are equal + //////////////////////////////////////////////////////////// + public override readonly bool Equals(object obj) => obj is BlendMode mode && Equals(mode); + + /////////////////////////////////////////////////////////// + /// + /// Compare two blend modes and checks if they are equal + /// + /// Blend Mode to check + /// blend modes are equal + //////////////////////////////////////////////////////////// + public readonly bool Equals(BlendMode other) => ColorSrcFactor == other.ColorSrcFactor && + ColorDstFactor == other.ColorDstFactor && + ColorEquation == other.ColorEquation && + AlphaSrcFactor == other.AlphaSrcFactor && + AlphaDstFactor == other.AlphaDstFactor && + AlphaEquation == other.AlphaEquation; + + //////////////////////////////////////////////////////////// + /// + /// Provide a integer describing the object + /// + /// Integer description of the object + //////////////////////////////////////////////////////////// + public override readonly int GetHashCode() => ColorSrcFactor.GetHashCode() ^ + ColorDstFactor.GetHashCode() ^ + ColorEquation.GetHashCode() ^ + AlphaSrcFactor.GetHashCode() ^ + AlphaDstFactor.GetHashCode() ^ + AlphaEquation.GetHashCode(); + + /// Source blending factor for the color channels + public Factor ColorSrcFactor; + + /// Destination blending factor for the color channels + public Factor ColorDstFactor; + + /// Blending equation for the color channels + public Equation ColorEquation; + + /// Source blending factor for the alpha channel + public Factor AlphaSrcFactor; + + /// Destination blending factor for the alpha channel + public Factor AlphaDstFactor; + + /// Blending equation for the alpha channel + public Equation AlphaEquation; } diff --git a/src/SFML.Graphics/CircleShape.cs b/src/SFML.Graphics/CircleShape.cs index 53b32a0c..f2ab87a6 100644 --- a/src/SFML.Graphics/CircleShape.cs +++ b/src/SFML.Graphics/CircleShape.cs @@ -3,126 +3,125 @@ using System.Security; using SFML.System; -namespace SFML.Graphics +namespace SFML.Graphics; + +//////////////////////////////////////////////////////////// +/// +/// Specialized shape representing a circle +/// +//////////////////////////////////////////////////////////// +public class CircleShape : Shape { //////////////////////////////////////////////////////////// /// - /// Specialized shape representing a circle + /// Default constructor /// //////////////////////////////////////////////////////////// - public class CircleShape : Shape - { - //////////////////////////////////////////////////////////// - /// - /// Default constructor - /// - //////////////////////////////////////////////////////////// - public CircleShape() : this(0) { } + public CircleShape() : this(0) { } - //////////////////////////////////////////////////////////// - /// - /// Construct the shape with an initial radius - /// - /// Radius of the shape - //////////////////////////////////////////////////////////// - public CircleShape(float radius) : this(radius, 30) { } + //////////////////////////////////////////////////////////// + /// + /// Construct the shape with an initial radius + /// + /// Radius of the shape + //////////////////////////////////////////////////////////// + public CircleShape(float radius) : this(radius, 30) { } - //////////////////////////////////////////////////////////// - /// - /// Construct the shape with an initial radius and point count - /// - /// Radius of the shape - /// Number of points of the shape - //////////////////////////////////////////////////////////// - public CircleShape(float radius, uint pointCount) - { - Radius = radius; - SetPointCount(pointCount); - } + //////////////////////////////////////////////////////////// + /// + /// Construct the shape with an initial radius and point count + /// + /// Radius of the shape + /// Number of points of the shape + //////////////////////////////////////////////////////////// + public CircleShape(float radius, uint pointCount) + { + Radius = radius; + SetPointCount(pointCount); + } - //////////////////////////////////////////////////////////// - /// - /// Construct the shape from another shape - /// - /// Shape to copy - //////////////////////////////////////////////////////////// - public CircleShape(CircleShape copy) : base(copy) - { - Radius = copy.Radius; - SetPointCount(copy.GetPointCount()); - } + //////////////////////////////////////////////////////////// + /// + /// Construct the shape from another shape + /// + /// Shape to copy + //////////////////////////////////////////////////////////// + public CircleShape(CircleShape copy) : base(copy) + { + Radius = copy.Radius; + SetPointCount(copy.GetPointCount()); + } - //////////////////////////////////////////////////////////// - /// - /// The radius of the shape - /// - //////////////////////////////////////////////////////////// - public float Radius - { - get => _radius; - set { _radius = value; Update(); } - } + //////////////////////////////////////////////////////////// + /// + /// The radius of the shape + /// + //////////////////////////////////////////////////////////// + public float Radius + { + get => _radius; + set { _radius = value; Update(); } + } - //////////////////////////////////////////////////////////// - /// - /// Get the total number of points of the circle - /// - /// The total point count - //////////////////////////////////////////////////////////// - public override uint GetPointCount() => _pointCount; + //////////////////////////////////////////////////////////// + /// + /// Get the total number of points of the circle + /// + /// The total point count + //////////////////////////////////////////////////////////// + public override uint GetPointCount() => _pointCount; - //////////////////////////////////////////////////////////// - /// - /// Set the number of points of the circle. - /// The count must be greater than 2 to define a valid shape. - /// - /// New number of points of the circle - //////////////////////////////////////////////////////////// - public void SetPointCount(uint count) - { - _pointCount = count; - Update(); - } + //////////////////////////////////////////////////////////// + /// + /// Set the number of points of the circle. + /// The count must be greater than 2 to define a valid shape. + /// + /// New number of points of the circle + //////////////////////////////////////////////////////////// + public void SetPointCount(uint count) + { + _pointCount = count; + Update(); + } - //////////////////////////////////////////////////////////// - /// - /// 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. - /// - /// Index of the point to get, in range [0 .. PointCount - 1] - /// index-th point of the shape - //////////////////////////////////////////////////////////// - public override Vector2f GetPoint(uint index) - { - var angle = (float)((index * 2 * Math.PI / _pointCount) - (Math.PI / 2)); - var x = (float)Math.Cos(angle) * _radius; - var y = (float)Math.Sin(angle) * _radius; + //////////////////////////////////////////////////////////// + /// + /// 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. + /// + /// Index of the point to get, in range [0 .. PointCount - 1] + /// index-th point of the shape + //////////////////////////////////////////////////////////// + public override Vector2f GetPoint(uint index) + { + var angle = (float)((index * 2 * Math.PI / _pointCount) - (Math.PI / 2)); + var x = (float)Math.Cos(angle) * _radius; + var y = (float)Math.Sin(angle) * _radius; - return new Vector2f(_radius + x, _radius + y); - } + return new Vector2f(_radius + x, _radius + y); + } - //////////////////////////////////////////////////////////// - /// - /// 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. - /// - /// The geometric center of the shape - //////////////////////////////////////////////////////////// - public override Vector2f GetGeometricCenter() => sfCircleShape_getGeometricCenter(CPointer); + //////////////////////////////////////////////////////////// + /// + /// 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. + /// + /// The geometric center of the shape + //////////////////////////////////////////////////////////// + public override Vector2f GetGeometricCenter() => sfCircleShape_getGeometricCenter(CPointer); - private float _radius; - private uint _pointCount; + private float _radius; + private uint _pointCount; - #region Imports - [DllImport(CSFML.Graphics, CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] - private static extern Vector2f sfCircleShape_getGeometricCenter(IntPtr cPointer); - #endregion - } + #region Imports + [DllImport(CSFML.Graphics, CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] + private static extern Vector2f sfCircleShape_getGeometricCenter(IntPtr cPointer); + #endregion } diff --git a/src/SFML.Graphics/Color.cs b/src/SFML.Graphics/Color.cs index 52b3dcb8..d152a308 100644 --- a/src/SFML.Graphics/Color.cs +++ b/src/SFML.Graphics/Color.cs @@ -1,220 +1,219 @@ using System; using System.Runtime.InteropServices; -namespace SFML.Graphics +namespace SFML.Graphics; + +//////////////////////////////////////////////////////////// +/// +/// Utility class for manipulating 32-bits RGBA colors +/// +//////////////////////////////////////////////////////////// +[StructLayout(LayoutKind.Sequential)] +public struct Color : IEquatable { //////////////////////////////////////////////////////////// /// - /// Utility class for manipulating 32-bits RGBA colors + /// Construct the color from its red, green and blue components /// + /// Red component + /// Green component + /// Blue component //////////////////////////////////////////////////////////// - [StructLayout(LayoutKind.Sequential)] - public struct Color : IEquatable + public Color(byte red, byte green, byte blue) : this(red, green, blue, 255) { } + + //////////////////////////////////////////////////////////// + /// + /// Construct the color from its red, green, blue and alpha components + /// + /// Red component + /// Green component + /// Blue component + /// Alpha (transparency) component + //////////////////////////////////////////////////////////// + public Color(byte red, byte green, byte blue, byte alpha) { - //////////////////////////////////////////////////////////// - /// - /// Construct the color from its red, green and blue components - /// - /// Red component - /// Green component - /// Blue component - //////////////////////////////////////////////////////////// - public Color(byte red, byte green, byte blue) : this(red, green, blue, 255) { } - - //////////////////////////////////////////////////////////// - /// - /// Construct the color from its red, green, blue and alpha components - /// - /// Red component - /// Green component - /// Blue component - /// Alpha (transparency) component - //////////////////////////////////////////////////////////// - public Color(byte red, byte green, byte blue, byte alpha) - { - R = red; - G = green; - B = blue; - A = alpha; - } + R = red; + G = green; + B = blue; + A = alpha; + } - //////////////////////////////////////////////////////////// - /// - /// Construct the color from 32-bit unsigned integer - /// - /// Number containing the RGBA components (in that order) - //////////////////////////////////////////////////////////// - public Color(uint color) + //////////////////////////////////////////////////////////// + /// + /// Construct the color from 32-bit unsigned integer + /// + /// Number containing the RGBA components (in that order) + //////////////////////////////////////////////////////////// + public Color(uint color) + { + unchecked { - unchecked - { - R = (byte)(color >> 24); - G = (byte)(color >> 16); - B = (byte)(color >> 8); - A = (byte)color; - } + R = (byte)(color >> 24); + G = (byte)(color >> 16); + B = (byte)(color >> 8); + A = (byte)color; } + } - //////////////////////////////////////////////////////////// - /// - /// Construct the color from another - /// - /// Color to copy - //////////////////////////////////////////////////////////// - public Color(Color color) : this(color.R, color.G, color.B, color.A) { } - - //////////////////////////////////////////////////////////// - /// - /// Convert a color to a 32-bit unsigned integer - /// - /// Color represented as a 32-bit unsigned integer - //////////////////////////////////////////////////////////// - public uint ToInteger() => (uint)((R << 24) | (G << 16) | (B << 8) | A); - - //////////////////////////////////////////////////////////// - /// - /// Provide a string describing the object - /// - /// String description of the object - //////////////////////////////////////////////////////////// - public override string ToString() => $"[Color] R({R}) G({G}) B({B}) A({A})"; - - /// - /// Deconstructs a Color into a tuple of bytes - /// - /// Red component - /// Green component - /// Blue component - /// Alpha (transparency) component - public void Deconstruct(out byte red, out byte green, out byte blue, out byte alpha) - { - red = R; - green = G; - blue = B; - alpha = A; - } + //////////////////////////////////////////////////////////// + /// + /// Construct the color from another + /// + /// Color to copy + //////////////////////////////////////////////////////////// + public Color(Color color) : this(color.R, color.G, color.B, color.A) { } + + //////////////////////////////////////////////////////////// + /// + /// Convert a color to a 32-bit unsigned integer + /// + /// Color represented as a 32-bit unsigned integer + //////////////////////////////////////////////////////////// + public readonly uint ToInteger() => (uint)((R << 24) | (G << 16) | (B << 8) | A); - //////////////////////////////////////////////////////////// - /// - /// Compare color and object and checks if they are equal - /// - /// Object to check - /// Object and color are equal - //////////////////////////////////////////////////////////// - public override bool Equals(object obj) => (obj is Color) && Equals((Color)obj); - - /////////////////////////////////////////////////////////// - /// - /// Compare two colors and checks if they are equal - /// - /// Color to check - /// Colors are equal - //////////////////////////////////////////////////////////// - public bool Equals(Color other) => (R == other.R) && (G == other.G) && (B == other.B) && (A == other.A); - - //////////////////////////////////////////////////////////// - /// - /// Provide a integer describing the object - /// - /// Integer description of the object - //////////////////////////////////////////////////////////// - public override int GetHashCode() => (R << 24) | (G << 16) | (B << 8) | A; - - //////////////////////////////////////////////////////////// - /// - /// Compare two colors and checks if they are equal - /// - /// Colors are equal - //////////////////////////////////////////////////////////// - public static bool operator ==(Color left, Color right) => left.Equals(right); - - //////////////////////////////////////////////////////////// - /// - /// Compare two colors and checks if they are not equal - /// - /// Colors are not equal - //////////////////////////////////////////////////////////// - public static bool operator !=(Color left, Color right) => !left.Equals(right); - - //////////////////////////////////////////////////////////// - /// - /// This operator returns the component-wise sum of two colors. - /// Components that exceed 255 are clamped to 255. - /// - /// Result of left + right - //////////////////////////////////////////////////////////// - public static Color operator +(Color left, Color right) => new Color((byte)Math.Min(left.R + right.R, 255), - (byte)Math.Min(left.G + right.G, 255), - (byte)Math.Min(left.B + right.B, 255), - (byte)Math.Min(left.A + right.A, 255)); - - //////////////////////////////////////////////////////////// - /// - /// This operator returns the component-wise subtraction of two colors. - /// Components below 0 are clamped to 0. - /// - /// Result of left - right - //////////////////////////////////////////////////////////// - public static Color operator -(Color left, Color right) => new Color((byte)Math.Max(left.R - right.R, 0), - (byte)Math.Max(left.G - right.G, 0), - (byte)Math.Max(left.B - right.B, 0), - (byte)Math.Max(left.A - right.A, 0)); - - //////////////////////////////////////////////////////////// - /// - /// This operator returns the component-wise multiplication of two colors. - /// Components above 255 are clamped to 255. - /// - /// Result of left * right - //////////////////////////////////////////////////////////// - public static Color operator *(Color left, Color right) => new Color((byte)(left.R * right.R / 255), - (byte)(left.G * right.G / 255), - (byte)(left.B * right.B / 255), - (byte)(left.A * right.A / 255)); - - /// - /// Converts a tuple of bytes to a Color - /// - /// The tuple to convert - public static implicit operator Color((byte R, byte G, byte B, byte A) tuple) => new Color(tuple.R, tuple.G, tuple.B, tuple.A); - - /// Red component of the color - public byte R; - - /// Green component of the color - public byte G; - - /// Blue component of the color - public byte B; - - /// Alpha (transparent) component of the color - public byte A; - - /// Predefined black color - public static readonly Color Black = new Color(0, 0, 0); - - /// Predefined white color - public static readonly Color White = new Color(255, 255, 255); - - /// Predefined red color - public static readonly Color Red = new Color(255, 0, 0); - - /// Predefined green color - public static readonly Color Green = new Color(0, 255, 0); - - /// Predefined blue color - public static readonly Color Blue = new Color(0, 0, 255); - - /// Predefined yellow color - public static readonly Color Yellow = new Color(255, 255, 0); - - /// Predefined magenta color - public static readonly Color Magenta = new Color(255, 0, 255); - - /// Predefined cyan color - public static readonly Color Cyan = new Color(0, 255, 255); - - /// Predefined (black) transparent color - public static readonly Color Transparent = new Color(0, 0, 0, 0); + //////////////////////////////////////////////////////////// + /// + /// Provide a string describing the object + /// + /// String description of the object + //////////////////////////////////////////////////////////// + public override readonly string ToString() => $"[Color] R({R}) G({G}) B({B}) A({A})"; + + /// + /// Deconstructs a Color into a tuple of bytes + /// + /// Red component + /// Green component + /// Blue component + /// Alpha (transparency) component + public readonly void Deconstruct(out byte red, out byte green, out byte blue, out byte alpha) + { + red = R; + green = G; + blue = B; + alpha = A; } + + //////////////////////////////////////////////////////////// + /// + /// Compare color and object and checks if they are equal + /// + /// Object to check + /// Object and color are equal + //////////////////////////////////////////////////////////// + public override readonly bool Equals(object obj) => obj is Color color && Equals(color); + + /////////////////////////////////////////////////////////// + /// + /// Compare two colors and checks if they are equal + /// + /// Color to check + /// Colors are equal + //////////////////////////////////////////////////////////// + public readonly bool Equals(Color other) => R == other.R && G == other.G && B == other.B && A == other.A; + + //////////////////////////////////////////////////////////// + /// + /// Provide a integer describing the object + /// + /// Integer description of the object + //////////////////////////////////////////////////////////// + public override readonly int GetHashCode() => (R << 24) | (G << 16) | (B << 8) | A; + + //////////////////////////////////////////////////////////// + /// + /// Compare two colors and checks if they are equal + /// + /// Colors are equal + //////////////////////////////////////////////////////////// + public static bool operator ==(Color left, Color right) => left.Equals(right); + + //////////////////////////////////////////////////////////// + /// + /// Compare two colors and checks if they are not equal + /// + /// Colors are not equal + //////////////////////////////////////////////////////////// + public static bool operator !=(Color left, Color right) => !left.Equals(right); + + //////////////////////////////////////////////////////////// + /// + /// This operator returns the component-wise sum of two colors. + /// Components that exceed 255 are clamped to 255. + /// + /// Result of left + right + //////////////////////////////////////////////////////////// + public static Color operator +(Color left, Color right) => new((byte)Math.Min(left.R + right.R, 255), + (byte)Math.Min(left.G + right.G, 255), + (byte)Math.Min(left.B + right.B, 255), + (byte)Math.Min(left.A + right.A, 255)); + + //////////////////////////////////////////////////////////// + /// + /// This operator returns the component-wise subtraction of two colors. + /// Components below 0 are clamped to 0. + /// + /// Result of left - right + //////////////////////////////////////////////////////////// + public static Color operator -(Color left, Color right) => new((byte)Math.Max(left.R - right.R, 0), + (byte)Math.Max(left.G - right.G, 0), + (byte)Math.Max(left.B - right.B, 0), + (byte)Math.Max(left.A - right.A, 0)); + + //////////////////////////////////////////////////////////// + /// + /// This operator returns the component-wise multiplication of two colors. + /// Components above 255 are clamped to 255. + /// + /// Result of left * right + //////////////////////////////////////////////////////////// + public static Color operator *(Color left, Color right) => new((byte)(left.R * right.R / 255), + (byte)(left.G * right.G / 255), + (byte)(left.B * right.B / 255), + (byte)(left.A * right.A / 255)); + + /// + /// Converts a tuple of bytes to a Color + /// + /// The tuple to convert + public static implicit operator Color((byte R, byte G, byte B, byte A) tuple) => new(tuple.R, tuple.G, tuple.B, tuple.A); + + /// Red component of the color + public byte R; + + /// Green component of the color + public byte G; + + /// Blue component of the color + public byte B; + + /// Alpha (transparent) component of the color + public byte A; + + /// Predefined black color + public static readonly Color Black = new(0, 0, 0); + + /// Predefined white color + public static readonly Color White = new(255, 255, 255); + + /// Predefined red color + public static readonly Color Red = new(255, 0, 0); + + /// Predefined green color + public static readonly Color Green = new(0, 255, 0); + + /// Predefined blue color + public static readonly Color Blue = new(0, 0, 255); + + /// Predefined yellow color + public static readonly Color Yellow = new(255, 255, 0); + + /// Predefined magenta color + public static readonly Color Magenta = new(255, 0, 255); + + /// Predefined cyan color + public static readonly Color Cyan = new(0, 255, 255); + + /// Predefined (black) transparent color + public static readonly Color Transparent = new(0, 0, 0, 0); } diff --git a/src/SFML.Graphics/ConvexShape.cs b/src/SFML.Graphics/ConvexShape.cs index ef9d4a59..609bc37b 100644 --- a/src/SFML.Graphics/ConvexShape.cs +++ b/src/SFML.Graphics/ConvexShape.cs @@ -1,99 +1,98 @@ using System; using SFML.System; -namespace SFML.Graphics +namespace SFML.Graphics; + +//////////////////////////////////////////////////////////// +/// +/// Specialized shape representing a convex polygon +/// +//////////////////////////////////////////////////////////// +public class ConvexShape : Shape { //////////////////////////////////////////////////////////// /// - /// Specialized shape representing a convex polygon + /// Default constructor /// //////////////////////////////////////////////////////////// - public class ConvexShape : Shape - { - //////////////////////////////////////////////////////////// - /// - /// Default constructor - /// - //////////////////////////////////////////////////////////// - public ConvexShape() : this(0) { } + public ConvexShape() : this(0) { } - //////////////////////////////////////////////////////////// - /// - /// Construct the shape with an initial point count - /// - /// Number of points of the shape - //////////////////////////////////////////////////////////// - public ConvexShape(uint pointCount) => SetPointCount(pointCount); + //////////////////////////////////////////////////////////// + /// + /// Construct the shape with an initial point count + /// + /// Number of points of the shape + //////////////////////////////////////////////////////////// + public ConvexShape(uint pointCount) => SetPointCount(pointCount); - //////////////////////////////////////////////////////////// - /// - /// Construct the shape from another shape - /// - /// Shape to copy - //////////////////////////////////////////////////////////// - public ConvexShape(ConvexShape copy) : base(copy) + //////////////////////////////////////////////////////////// + /// + /// Construct the shape from another shape + /// + /// Shape to copy + //////////////////////////////////////////////////////////// + public ConvexShape(ConvexShape copy) : base(copy) + { + SetPointCount(copy.GetPointCount()); + for (uint i = 0; i < copy.GetPointCount(); ++i) { - SetPointCount(copy.GetPointCount()); - for (uint i = 0; i < copy.GetPointCount(); ++i) - { - SetPoint(i, copy.GetPoint(i)); - } + SetPoint(i, copy.GetPoint(i)); } + } - //////////////////////////////////////////////////////////// - /// - /// Get the total number of points of the polygon - /// - /// The total point count - //////////////////////////////////////////////////////////// - public override uint GetPointCount() => (uint)(_points?.Length ?? 0); - - //////////////////////////////////////////////////////////// - /// - /// Set the number of points of the polygon. - /// The count must be greater than 2 to define a valid shape. - /// - /// New number of points of the polygon - //////////////////////////////////////////////////////////// - public void SetPointCount(uint count) - { - Array.Resize(ref _points, (int)count); - Update(); - } + //////////////////////////////////////////////////////////// + /// + /// Get the total number of points of the polygon + /// + /// The total point count + //////////////////////////////////////////////////////////// + public override uint GetPointCount() => (uint)(_points?.Length ?? 0); - //////////////////////////////////////////////////////////// - /// - /// 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. - /// - /// Index of the point to get, in range [0 .. PointCount - 1] - /// index-th point of the shape - //////////////////////////////////////////////////////////// - public override Vector2f GetPoint(uint index) => _points[index]; + //////////////////////////////////////////////////////////// + /// + /// Set the number of points of the polygon. + /// The count must be greater than 2 to define a valid shape. + /// + /// New number of points of the polygon + //////////////////////////////////////////////////////////// + public void SetPointCount(uint count) + { + Array.Resize(ref _points, (int)count); + Update(); + } - //////////////////////////////////////////////////////////// - /// - /// Set the position of a point. - /// - /// Don't forget that the polygon must remain convex, and - /// the points need to stay ordered! - /// PointCount must be set first in order to set the total - /// number of points. The result is undefined if index is out - /// of the valid range. - /// - /// Index of the point to change, in range [0 .. PointCount - 1] - /// New position of the point - //////////////////////////////////////////////////////////// - public void SetPoint(uint index, Vector2f point) - { - _points[index] = point; - Update(); - } + //////////////////////////////////////////////////////////// + /// + /// 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. + /// + /// Index of the point to get, in range [0 .. PointCount - 1] + /// index-th point of the shape + //////////////////////////////////////////////////////////// + public override Vector2f GetPoint(uint index) => _points[index]; - private Vector2f[] _points; + //////////////////////////////////////////////////////////// + /// + /// Set the position of a point. + /// + /// Don't forget that the polygon must remain convex, and + /// the points need to stay ordered! + /// PointCount must be set first in order to set the total + /// number of points. The result is undefined if index is out + /// of the valid range. + /// + /// Index of the point to change, in range [0 .. PointCount - 1] + /// New position of the point + //////////////////////////////////////////////////////////// + public void SetPoint(uint index, Vector2f point) + { + _points[index] = point; + Update(); } + + private Vector2f[] _points; } diff --git a/src/SFML.Graphics/CoordinateType.cs b/src/SFML.Graphics/CoordinateType.cs index fd249b1c..be5cf2b5 100644 --- a/src/SFML.Graphics/CoordinateType.cs +++ b/src/SFML.Graphics/CoordinateType.cs @@ -1,13 +1,12 @@ -namespace SFML.Graphics +namespace SFML.Graphics; + +/// +/// Types of texture coordinates that can be used for rendering. +/// +public enum CoordinateType { - /// - /// Types of texture coordinates that can be used for rendering. - /// - public enum CoordinateType - { - /// Texture coordinates in range [0 .. 1]. - Normalized, - /// Texture coordinates in range [0 .. size]. - Pixels - } + /// Texture coordinates in range [0 .. 1]. + Normalized, + /// Texture coordinates in range [0 .. size]. + Pixels } \ No newline at end of file diff --git a/src/SFML.Graphics/Font.cs b/src/SFML.Graphics/Font.cs index 1628bb1a..c235f59c 100644 --- a/src/SFML.Graphics/Font.cs +++ b/src/SFML.Graphics/Font.cs @@ -6,343 +6,334 @@ using SFML.System; using SFML.Window; -namespace SFML.Graphics +namespace SFML.Graphics; + +//////////////////////////////////////////////////////////// +/// +/// Font is the low-level class for loading and +/// manipulating character fonts. This class is meant to +/// be used by String2D +/// +//////////////////////////////////////////////////////////// +public class Font : ObjectBase { //////////////////////////////////////////////////////////// /// - /// Font is the low-level class for loading and - /// manipulating character fonts. This class is meant to - /// be used by String2D + /// Construct the font from a file /// + /// Font file to load + /// //////////////////////////////////////////////////////////// - public class Font : ObjectBase + public Font(string filename) : base(sfFont_createFromFile(filename)) { - //////////////////////////////////////////////////////////// - /// - /// Construct the font from a file - /// - /// Font file to load - /// - //////////////////////////////////////////////////////////// - public Font(string filename) : base(sfFont_createFromFile(filename)) + if (IsInvalid) { - if (IsInvalid) - { - throw new LoadingFailedException("font", filename); - } + throw new LoadingFailedException("font", filename); } + } - //////////////////////////////////////////////////////////// - /// - /// Construct the font from a custom stream - /// - /// Source stream to read from - /// - //////////////////////////////////////////////////////////// - public Font(Stream stream) : base(IntPtr.Zero) - { - // Stream needs to stay alive as long as the Font instance is alive - // Disposing of it can only be done in Font's Dispose method - _myStream = new StreamAdaptor(stream); - CPointer = sfFont_createFromStream(_myStream.InputStreamPtr); - - if (IsInvalid) - { - throw new LoadingFailedException("font"); - } - } + //////////////////////////////////////////////////////////// + /// + /// Construct the font from a custom stream + /// + /// Source stream to read from + /// + //////////////////////////////////////////////////////////// + public Font(Stream stream) : base(IntPtr.Zero) + { + // Stream needs to stay alive as long as the Font instance is alive + // Disposing of it can only be done in Font's Dispose method + _myStream = new StreamAdaptor(stream); + CPointer = sfFont_createFromStream(_myStream.InputStreamPtr); - //////////////////////////////////////////////////////////// - /// - /// Construct the font from a file in memory - /// - /// Byte array containing the file contents - /// - //////////////////////////////////////////////////////////// - public Font(byte[] bytes) : - base(IntPtr.Zero) + if (IsInvalid) { - // Memory needs to stay pinned as long as the Font instance is alive - // Freeing the handle can only be done in Font's Dispose method - _myBytesPin = GCHandle.Alloc(bytes, GCHandleType.Pinned); - CPointer = sfFont_createFromMemory(_myBytesPin.AddrOfPinnedObject(), (UIntPtr)bytes.Length); - - if (IsInvalid) - { - _myBytesPin.Free(); - throw new LoadingFailedException("font"); - } + throw new LoadingFailedException("font"); } + } + + //////////////////////////////////////////////////////////// + /// + /// Construct the font from a file in memory + /// + /// Byte array containing the file contents + /// + //////////////////////////////////////////////////////////// + public Font(byte[] bytes) : + base(IntPtr.Zero) + { + // Memory needs to stay pinned as long as the Font instance is alive + // Freeing the handle can only be done in Font's Dispose method + _myBytesPin = GCHandle.Alloc(bytes, GCHandleType.Pinned); + CPointer = sfFont_createFromMemory(_myBytesPin.AddrOfPinnedObject(), (UIntPtr)bytes.Length); - //////////////////////////////////////////////////////////// - /// - /// Construct the font from another font - /// - /// Font to copy - //////////////////////////////////////////////////////////// - public Font(Font copy) : base(sfFont_copy(copy.CPointer)) { } - - //////////////////////////////////////////////////////////// - /// - /// Get a glyph in the font - /// - /// Unicode code point of the character to get - /// Character size - /// Retrieve the bold version or the regular one? - /// Thickness of outline (when != 0 the glyph will not be filled) - /// The glyph corresponding to the character - //////////////////////////////////////////////////////////// - public Glyph GetGlyph(uint codePoint, uint characterSize, bool bold, float outlineThickness) => sfFont_getGlyph(CPointer, codePoint, characterSize, bold, outlineThickness); - - //////////////////////////////////////////////////////////// - /// - /// 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. - /// - /// Unicode code point to check - /// True if the codepoint has a glyph representation, false otherwise - //////////////////////////////////////////////////////////// - public bool HasGlyph(uint codePoint) => sfFont_hasGlyph(CPointer, codePoint); - - //////////////////////////////////////////////////////////// - /// - /// Get the kerning value corresponding to a given pair of - /// characters in a font - /// - /// Unicode code point of the first character - /// Unicode code point of the second character - /// Character size, in pixels - /// Kerning offset, in pixels - //////////////////////////////////////////////////////////// - public float GetKerning(uint first, uint second, uint characterSize) => sfFont_getKerning(CPointer, first, second, characterSize); - - //////////////////////////////////////////////////////////// - /// - /// Get the bold kerning value corresponding to a given pair - /// of characters in a font - /// - /// Unicode code point of the first character - /// Unicode code point of the second character - /// Character size, in pixels - /// Kerning offset, in pixels - //////////////////////////////////////////////////////////// - public float GetBoldKerning(uint first, uint second, uint characterSize) => sfFont_getBoldKerning(CPointer, first, second, characterSize); - - //////////////////////////////////////////////////////////// - /// - /// Get spacing between two consecutive lines - /// - /// Character size - /// Line spacing, in pixels - //////////////////////////////////////////////////////////// - public float GetLineSpacing(uint characterSize) => sfFont_getLineSpacing(CPointer, characterSize); - - //////////////////////////////////////////////////////////// - /// - /// Get the position of the underline - /// - /// Character size - /// Underline position, in pixels - //////////////////////////////////////////////////////////// - public float GetUnderlinePosition(uint characterSize) => sfFont_getUnderlinePosition(CPointer, characterSize); - - //////////////////////////////////////////////////////////// - /// - /// Get the thickness of the underline - /// - /// Character size - /// Underline thickness, in pixels - //////////////////////////////////////////////////////////// - public float GetUnderlineThickness(uint characterSize) => sfFont_getUnderlineThickness(CPointer, characterSize); - - //////////////////////////////////////////////////////////// - /// - /// Get the texture containing the glyphs of a given size - /// - /// Character size - /// Texture storing the glyphs for the given size - //////////////////////////////////////////////////////////// - public Texture GetTexture(uint characterSize) + if (IsInvalid) { - _textures[characterSize] = new Texture(sfFont_getTexture(CPointer, characterSize)); - return _textures[characterSize]; + _myBytesPin.Free(); + throw new LoadingFailedException("font"); } + } - //////////////////////////////////////////////////////////// - /// - /// 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. - /// - /// True to enable smoothing, false to disable it - //////////////////////////////////////////////////////////// - public void SetSmooth(bool smooth) => sfFont_setSmooth(CPointer, smooth); - - //////////////////////////////////////////////////////////// - /// - /// Tell whether the smooth filter is enabled or disabled - /// - /// True if smoothing is enabled, false if it is disabled - //////////////////////////////////////////////////////////// - public bool IsSmooth() => sfFont_isSmooth(CPointer); - - //////////////////////////////////////////////////////////// - /// - /// Get the font information - /// - /// A structure that holds the font information - //////////////////////////////////////////////////////////// - public Info GetInfo() - { - var data = sfFont_getInfo(CPointer); - var info = new Info - { - Family = Marshal.PtrToStringAnsi(data.Family) - }; + //////////////////////////////////////////////////////////// + /// + /// Construct the font from another font + /// + /// Font to copy + //////////////////////////////////////////////////////////// + public Font(Font copy) : base(sfFont_copy(copy.CPointer)) { } - return info; - } + //////////////////////////////////////////////////////////// + /// + /// Get a glyph in the font + /// + /// Unicode code point of the character to get + /// Character size + /// Retrieve the bold version or the regular one? + /// Thickness of outline (when != 0 the glyph will not be filled) + /// The glyph corresponding to the character + //////////////////////////////////////////////////////////// + public Glyph GetGlyph(uint codePoint, uint characterSize, bool bold, float outlineThickness) => sfFont_getGlyph(CPointer, codePoint, characterSize, bold, outlineThickness); + + //////////////////////////////////////////////////////////// + /// + /// 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. + /// + /// Unicode code point to check + /// True if the codepoint has a glyph representation, false otherwise + //////////////////////////////////////////////////////////// + public bool HasGlyph(uint codePoint) => sfFont_hasGlyph(CPointer, codePoint); + + //////////////////////////////////////////////////////////// + /// + /// Get the kerning value corresponding to a given pair of + /// characters in a font + /// + /// Unicode code point of the first character + /// Unicode code point of the second character + /// Character size, in pixels + /// Kerning offset, in pixels + //////////////////////////////////////////////////////////// + public float GetKerning(uint first, uint second, uint characterSize) => sfFont_getKerning(CPointer, first, second, characterSize); - //////////////////////////////////////////////////////////// - /// - /// Provide a string describing the object - /// - /// String description of the object - //////////////////////////////////////////////////////////// - public override string ToString() => nameof(Font); - - //////////////////////////////////////////////////////////// - /// - /// Handle the destruction of the object - /// - /// Is the GC disposing the object, or is it an explicit call? - //////////////////////////////////////////////////////////// - protected override void Destroy(bool disposing) + //////////////////////////////////////////////////////////// + /// + /// Get the bold kerning value corresponding to a given pair + /// of characters in a font + /// + /// Unicode code point of the first character + /// Unicode code point of the second character + /// Character size, in pixels + /// Kerning offset, in pixels + //////////////////////////////////////////////////////////// + public float GetBoldKerning(uint first, uint second, uint characterSize) => sfFont_getBoldKerning(CPointer, first, second, characterSize); + + //////////////////////////////////////////////////////////// + /// + /// Get spacing between two consecutive lines + /// + /// Character size + /// Line spacing, in pixels + //////////////////////////////////////////////////////////// + public float GetLineSpacing(uint characterSize) => sfFont_getLineSpacing(CPointer, characterSize); + + //////////////////////////////////////////////////////////// + /// + /// Get the position of the underline + /// + /// Character size + /// Underline position, in pixels + //////////////////////////////////////////////////////////// + public float GetUnderlinePosition(uint characterSize) => sfFont_getUnderlinePosition(CPointer, characterSize); + + //////////////////////////////////////////////////////////// + /// + /// Get the thickness of the underline + /// + /// Character size + /// Underline thickness, in pixels + //////////////////////////////////////////////////////////// + public float GetUnderlineThickness(uint characterSize) => sfFont_getUnderlineThickness(CPointer, characterSize); + + //////////////////////////////////////////////////////////// + /// + /// Get the texture containing the glyphs of a given size + /// + /// Character size + /// Texture storing the glyphs for the given size + //////////////////////////////////////////////////////////// + public Texture GetTexture(uint characterSize) + { + _textures[characterSize] = new Texture(sfFont_getTexture(CPointer, characterSize)); + return _textures[characterSize]; + } + + //////////////////////////////////////////////////////////// + /// + /// 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. + /// + /// True to enable smoothing, false to disable it + //////////////////////////////////////////////////////////// + public void SetSmooth(bool smooth) => sfFont_setSmooth(CPointer, smooth); + + //////////////////////////////////////////////////////////// + /// + /// Tell whether the smooth filter is enabled or disabled + /// + /// True if smoothing is enabled, false if it is disabled + //////////////////////////////////////////////////////////// + public bool IsSmooth() => sfFont_isSmooth(CPointer); + + //////////////////////////////////////////////////////////// + /// + /// Get the font information + /// + /// A structure that holds the font information + //////////////////////////////////////////////////////////// + public Info GetInfo() + { + var data = sfFont_getInfo(CPointer); + var info = new Info { - if (!disposing) - { - _ = Context.Global.SetActive(true); - } + Family = Marshal.PtrToStringAnsi(data.Family) + }; - sfFont_destroy(CPointer); + return info; + } - if (disposing) - { - foreach (var texture in _textures.Values) - { - texture.Dispose(); - } + //////////////////////////////////////////////////////////// + /// + /// Provide a string describing the object + /// + /// String description of the object + //////////////////////////////////////////////////////////// + public override string ToString() => nameof(Font); - _myStream?.Dispose(); - } + //////////////////////////////////////////////////////////// + /// + /// Handle the destruction of the object + /// + /// Is the GC disposing the object, or is it an explicit call? + //////////////////////////////////////////////////////////// + protected override void Destroy(bool disposing) + { + if (!disposing) + { + _ = Context.Global.SetActive(true); + } - if (_myBytesPin.IsAllocated) - { - _myBytesPin.Free(); - } + sfFont_destroy(CPointer); - if (!disposing) + if (disposing) + { + foreach (var texture in _textures.Values) { - _ = Context.Global.SetActive(false); + texture.Dispose(); } + + _myStream?.Dispose(); } - //////////////////////////////////////////////////////////// - /// - /// Internal constructor - /// - /// Pointer to the object in C library - //////////////////////////////////////////////////////////// - private Font(IntPtr cPointer) : base(cPointer) { } - - //////////////////////////////////////////////////////////// - /// - /// Info holds various information about a font - /// - //////////////////////////////////////////////////////////// - public struct Info + if (_myBytesPin.IsAllocated) { - /// The font family - public string Family; + _myBytesPin.Free(); } - //////////////////////////////////////////////////////////// - /// - /// Internal struct used for marshaling the font info - /// struct from unmanaged code. - /// - //////////////////////////////////////////////////////////// - [StructLayout(LayoutKind.Sequential)] - internal struct InfoMarshalData + if (!disposing) { - public IntPtr Family; + _ = Context.Global.SetActive(false); } + } - private readonly Dictionary _textures = new Dictionary(); - private readonly StreamAdaptor _myStream; - private GCHandle _myBytesPin; + //////////////////////////////////////////////////////////// + /// + /// Info holds various information about a font + /// + //////////////////////////////////////////////////////////// + public struct Info + { + /// The font family + public string Family; + } - #region Imports - [DllImport(CSFML.Graphics, CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] - private static extern IntPtr sfFont_createFromFile(string filename); + //////////////////////////////////////////////////////////// + /// + /// Internal struct used for marshaling the font info + /// struct from unmanaged code. + /// + //////////////////////////////////////////////////////////// + [StructLayout(LayoutKind.Sequential)] + internal struct InfoMarshalData + { + public IntPtr Family; + } - [DllImport(CSFML.Graphics, CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] - private static extern IntPtr sfFont_createFromStream(IntPtr stream); + private readonly Dictionary _textures = []; + private readonly StreamAdaptor _myStream; + private GCHandle _myBytesPin; - [DllImport(CSFML.Graphics, CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] - private static extern IntPtr sfFont_createFromMemory(IntPtr data, UIntPtr size); + #region Imports + [DllImport(CSFML.Graphics, CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] + private static extern IntPtr sfFont_createFromFile(string filename); - [DllImport(CSFML.Graphics, CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] - private static extern IntPtr sfFont_copy(IntPtr font); + [DllImport(CSFML.Graphics, CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] + private static extern IntPtr sfFont_createFromStream(IntPtr stream); - [DllImport(CSFML.Graphics, CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] - private static extern void sfFont_destroy(IntPtr cPointer); + [DllImport(CSFML.Graphics, CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] + private static extern IntPtr sfFont_createFromMemory(IntPtr data, UIntPtr size); - [DllImport(CSFML.Graphics, CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] - private static extern Glyph sfFont_getGlyph(IntPtr cPointer, uint codePoint, uint characterSize, bool bold, float outlineThickness); + [DllImport(CSFML.Graphics, CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] + private static extern IntPtr sfFont_copy(IntPtr font); - [DllImport(CSFML.Graphics, CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] - [return: MarshalAs(UnmanagedType.I1)] - private static extern bool sfFont_hasGlyph(IntPtr font, uint codePoint); + [DllImport(CSFML.Graphics, CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] + private static extern void sfFont_destroy(IntPtr cPointer); - [DllImport(CSFML.Graphics, CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] - private static extern float sfFont_getKerning(IntPtr cPointer, uint first, uint second, uint characterSize); + [DllImport(CSFML.Graphics, CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] + private static extern Glyph sfFont_getGlyph(IntPtr cPointer, uint codePoint, uint characterSize, bool bold, float outlineThickness); - [DllImport(CSFML.Graphics, CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] - private static extern float sfFont_getBoldKerning(IntPtr cPointer, uint first, uint second, uint characterSize); + [DllImport(CSFML.Graphics, CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] + [return: MarshalAs(UnmanagedType.I1)] + private static extern bool sfFont_hasGlyph(IntPtr font, uint codePoint); - [DllImport(CSFML.Graphics, CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] - private static extern float sfFont_getLineSpacing(IntPtr cPointer, uint characterSize); + [DllImport(CSFML.Graphics, CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] + private static extern float sfFont_getKerning(IntPtr cPointer, uint first, uint second, uint characterSize); - [DllImport(CSFML.Graphics, CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] - private static extern float sfFont_getUnderlinePosition(IntPtr cPointer, uint characterSize); + [DllImport(CSFML.Graphics, CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] + private static extern float sfFont_getBoldKerning(IntPtr cPointer, uint first, uint second, uint characterSize); - [DllImport(CSFML.Graphics, CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] - private static extern float sfFont_getUnderlineThickness(IntPtr cPointer, uint characterSize); + [DllImport(CSFML.Graphics, CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] + private static extern float sfFont_getLineSpacing(IntPtr cPointer, uint characterSize); - [DllImport(CSFML.Graphics, CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] - private static extern IntPtr sfFont_getTexture(IntPtr cPointer, uint characterSize); + [DllImport(CSFML.Graphics, CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] + private static extern float sfFont_getUnderlinePosition(IntPtr cPointer, uint characterSize); - [DllImport(CSFML.Graphics, CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] - private static extern void sfFont_setSmooth(IntPtr cPointer, bool smooth); + [DllImport(CSFML.Graphics, CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] + private static extern float sfFont_getUnderlineThickness(IntPtr cPointer, uint characterSize); - [DllImport(CSFML.Graphics, CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] - [return: MarshalAs(UnmanagedType.I1)] - private static extern bool sfFont_isSmooth(IntPtr cPointer); + [DllImport(CSFML.Graphics, CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] + private static extern IntPtr sfFont_getTexture(IntPtr cPointer, uint characterSize); - [DllImport(CSFML.Graphics, CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] - private static extern InfoMarshalData sfFont_getInfo(IntPtr cPointer); - #endregion - } + [DllImport(CSFML.Graphics, CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] + private static extern void sfFont_setSmooth(IntPtr cPointer, bool smooth); + + [DllImport(CSFML.Graphics, CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] + [return: MarshalAs(UnmanagedType.I1)] + private static extern bool sfFont_isSmooth(IntPtr cPointer); + + [DllImport(CSFML.Graphics, CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] + private static extern InfoMarshalData sfFont_getInfo(IntPtr cPointer); + #endregion } diff --git a/src/SFML.Graphics/Glsl.cs b/src/SFML.Graphics/Glsl.cs index 332cfd9e..02420504 100644 --- a/src/SFML.Graphics/Glsl.cs +++ b/src/SFML.Graphics/Glsl.cs @@ -1,556 +1,546 @@ using System.Runtime.InteropServices; using SFML.System; -namespace SFML.Graphics.Glsl +namespace SFML.Graphics.Glsl; + +#region 2D Vectors +//////////////////////////////////////////////////////////// +/// +/// is a struct represent a glsl vec2 value +/// +//////////////////////////////////////////////////////////// +[StructLayout(LayoutKind.Sequential)] +public struct Vec2 { - #region 2D Vectors //////////////////////////////////////////////////////////// /// - /// is a struct represent a glsl vec2 value + /// Implicit cast from to /// + public static implicit operator Vec2(Vector2f vec) => new(vec); + //////////////////////////////////////////////////////////// - [StructLayout(LayoutKind.Sequential)] - public struct Vec2 + /// + /// Construct the from its coordinates + /// + /// X coordinate + /// Y coordinate + //////////////////////////////////////////////////////////// + public Vec2(float x, float y) { - //////////////////////////////////////////////////////////// - /// - /// Implicit cast from to - /// - public static implicit operator Vec2(Vector2f vec) => new Vec2(vec); - - //////////////////////////////////////////////////////////// - /// - /// Construct the from its coordinates - /// - /// X coordinate - /// Y coordinate - //////////////////////////////////////////////////////////// - public Vec2(float x, float y) - { - X = x; - Y = y; - } - - //////////////////////////////////////////////////////////// - /// - /// Construct the from a standard SFML - /// - /// A standard SFML 2D vector - //////////////////////////////////////////////////////////// - public Vec2(Vector2f vec) - { - X = vec.X; - Y = vec.Y; - } - - /// Horizontal component of the vector - public float X; - - /// Vertical component of the vector - public float Y; + X = x; + Y = y; } //////////////////////////////////////////////////////////// /// - /// is a struct represent a glsl ivec2 value + /// Construct the from a standard SFML /// + /// A standard SFML 2D vector //////////////////////////////////////////////////////////// - [StructLayout(LayoutKind.Sequential)] - public struct Ivec2 + public Vec2(Vector2f vec) { - //////////////////////////////////////////////////////////// - /// - /// Implicit cast from to - /// - public static implicit operator Ivec2(Vector2i vec) => new Ivec2(vec); - - //////////////////////////////////////////////////////////// - /// - /// Construct the from its coordinates - /// - /// X coordinate - /// Y coordinate - //////////////////////////////////////////////////////////// - public Ivec2(int x, int y) - { - X = x; - Y = y; - } + X = vec.X; + Y = vec.Y; + } - //////////////////////////////////////////////////////////// - /// - /// Construct the from a standard SFML - /// - /// A standard SFML 2D integer vector - //////////////////////////////////////////////////////////// - public Ivec2(Vector2i vec) - { - X = vec.X; - Y = vec.Y; - } + /// Horizontal component of the vector + public float X; - /// Horizontal component of the vector - public int X; + /// Vertical component of the vector + public float Y; +} - /// Vertical component of the vector - public int Y; +//////////////////////////////////////////////////////////// +/// +/// is a struct represent a glsl ivec2 value +/// +//////////////////////////////////////////////////////////// +[StructLayout(LayoutKind.Sequential)] +public struct Ivec2 +{ + //////////////////////////////////////////////////////////// + /// + /// Implicit cast from to + /// + public static implicit operator Ivec2(Vector2i vec) => new(vec); + + //////////////////////////////////////////////////////////// + /// + /// Construct the from its coordinates + /// + /// X coordinate + /// Y coordinate + //////////////////////////////////////////////////////////// + public Ivec2(int x, int y) + { + X = x; + Y = y; } //////////////////////////////////////////////////////////// /// - /// is a struct represent a glsl bvec2 value + /// Construct the from a standard SFML /// + /// A standard SFML 2D integer vector //////////////////////////////////////////////////////////// - [StructLayout(LayoutKind.Sequential)] - public struct Bvec2 + public Ivec2(Vector2i vec) { - //////////////////////////////////////////////////////////// - /// - /// Construct the from its coordinates - /// - /// X coordinate - /// Y coordinate - //////////////////////////////////////////////////////////// - public Bvec2(bool x, bool y) - { - X = x; - Y = y; - } + X = vec.X; + Y = vec.Y; + } - /// Horizontal component of the vector - [MarshalAs(UnmanagedType.I1)] - public bool X; + /// Horizontal component of the vector + public int X; - /// Vertical component of the vector - [MarshalAs(UnmanagedType.I1)] - public bool Y; - } - #endregion + /// Vertical component of the vector + public int Y; +} - #region 3D Vectors +//////////////////////////////////////////////////////////// +/// +/// is a struct represent a glsl bvec2 value +/// +//////////////////////////////////////////////////////////// +[StructLayout(LayoutKind.Sequential)] +public struct Bvec2 +{ //////////////////////////////////////////////////////////// /// - /// is a struct represent a glsl vec3 value + /// Construct the from its coordinates /// + /// X coordinate + /// Y coordinate //////////////////////////////////////////////////////////// - [StructLayout(LayoutKind.Sequential)] - public struct Vec3 + public Bvec2(bool x, bool y) { - //////////////////////////////////////////////////////////// - /// - /// Implicit cast from to - /// - public static implicit operator Vec3(Vector3f vec) => new Vec3(vec); - - //////////////////////////////////////////////////////////// - /// - /// Construct the from its coordinates - /// - /// X coordinate - /// Y coordinate - /// Z coordinate - //////////////////////////////////////////////////////////// - public Vec3(float x, float y, float z) - { - X = x; - Y = y; - Z = z; - } - - //////////////////////////////////////////////////////////// - /// - /// Construct the from a standard SFML - /// - /// A standard SFML 3D vector - //////////////////////////////////////////////////////////// - public Vec3(Vector3f vec) - { - X = vec.X; - Y = vec.Y; - Z = vec.Z; - } + X = x; + Y = y; + } - /// Horizontal component of the vector - public float X; + /// Horizontal component of the vector + [MarshalAs(UnmanagedType.I1)] + public bool X; - /// Vertical component of the vector - public float Y; + /// Vertical component of the vector + [MarshalAs(UnmanagedType.I1)] + public bool Y; +} +#endregion + +#region 3D Vectors +//////////////////////////////////////////////////////////// +/// +/// is a struct represent a glsl vec3 value +/// +//////////////////////////////////////////////////////////// +[StructLayout(LayoutKind.Sequential)] +public struct Vec3 +{ + //////////////////////////////////////////////////////////// + /// + /// Implicit cast from to + /// + public static implicit operator Vec3(Vector3f vec) => new(vec); - /// Depth component of the vector - public float Z; + //////////////////////////////////////////////////////////// + /// + /// Construct the from its coordinates + /// + /// X coordinate + /// Y coordinate + /// Z coordinate + //////////////////////////////////////////////////////////// + public Vec3(float x, float y, float z) + { + X = x; + Y = y; + Z = z; } //////////////////////////////////////////////////////////// /// - /// is a struct represent a glsl ivec3 value + /// Construct the from a standard SFML /// + /// A standard SFML 3D vector //////////////////////////////////////////////////////////// - [StructLayout(LayoutKind.Sequential)] - public struct Ivec3 + public Vec3(Vector3f vec) { - //////////////////////////////////////////////////////////// - /// - /// Construct the from its coordinates - /// - /// X coordinate - /// Y coordinate - /// Z coordinate - //////////////////////////////////////////////////////////// - public Ivec3(int x, int y, int z) - { - X = x; - Y = y; - Z = z; - } + X = vec.X; + Y = vec.Y; + Z = vec.Z; + } - /// Horizontal component of the vector - public int X; + /// Horizontal component of the vector + public float X; - /// Vertical component of the vector - public int Y; + /// Vertical component of the vector + public float Y; - /// Depth component of the vector - public int Z; - } + /// Depth component of the vector + public float Z; +} +//////////////////////////////////////////////////////////// +/// +/// is a struct represent a glsl ivec3 value +/// +//////////////////////////////////////////////////////////// +[StructLayout(LayoutKind.Sequential)] +public struct Ivec3 +{ //////////////////////////////////////////////////////////// /// - /// is a struct represent a glsl bvec3 value + /// Construct the from its coordinates /// + /// X coordinate + /// Y coordinate + /// Z coordinate //////////////////////////////////////////////////////////// - [StructLayout(LayoutKind.Sequential)] - public struct Bvec3 + public Ivec3(int x, int y, int z) { - //////////////////////////////////////////////////////////// - /// - /// Construct the from its coordinates - /// - /// X coordinate - /// Y coordinate - /// Z coordinate - //////////////////////////////////////////////////////////// - public Bvec3(bool x, bool y, bool z) - { - X = x; - Y = y; - Z = z; - } + X = x; + Y = y; + Z = z; + } + + /// Horizontal component of the vector + public int X; - /// Horizontal component of the vector - [MarshalAs(UnmanagedType.I1)] - public bool X; + /// Vertical component of the vector + public int Y; - /// Vertical component of the vector - [MarshalAs(UnmanagedType.I1)] - public bool Y; + /// Depth component of the vector + public int Z; +} - /// Depth component of the vector - [MarshalAs(UnmanagedType.I1)] - public bool Z; +//////////////////////////////////////////////////////////// +/// +/// is a struct represent a glsl bvec3 value +/// +//////////////////////////////////////////////////////////// +[StructLayout(LayoutKind.Sequential)] +public struct Bvec3 +{ + //////////////////////////////////////////////////////////// + /// + /// Construct the from its coordinates + /// + /// X coordinate + /// Y coordinate + /// Z coordinate + //////////////////////////////////////////////////////////// + public Bvec3(bool x, bool y, bool z) + { + X = x; + Y = y; + Z = z; } - #endregion - #region 4D Vectors + /// Horizontal component of the vector + [MarshalAs(UnmanagedType.I1)] + public bool X; + + /// Vertical component of the vector + [MarshalAs(UnmanagedType.I1)] + public bool Y; + + /// Depth component of the vector + [MarshalAs(UnmanagedType.I1)] + public bool Z; +} +#endregion + +#region 4D Vectors +//////////////////////////////////////////////////////////// +/// +/// is a struct represent a glsl vec4 value +/// +//////////////////////////////////////////////////////////// +[StructLayout(LayoutKind.Sequential)] +public struct Vec4 +{ //////////////////////////////////////////////////////////// /// - /// is a struct represent a glsl vec4 value + /// Construct the from its coordinates /// + /// X coordinate + /// Y coordinate + /// Z coordinate + /// W coordinate //////////////////////////////////////////////////////////// - [StructLayout(LayoutKind.Sequential)] - public struct Vec4 + public Vec4(float x, float y, float z, float w) { - //////////////////////////////////////////////////////////// - /// - /// Construct the from its coordinates - /// - /// X coordinate - /// Y coordinate - /// Z coordinate - /// W coordinate - //////////////////////////////////////////////////////////// - public Vec4(float x, float y, float z, float w) - { - X = x; - Y = y; - Z = z; - W = w; - } + X = x; + Y = y; + Z = z; + W = w; + } - /// - /// Construct the from a - /// - /// - /// The 's values will be normalized from 0..255 to 0..1 - /// - /// A SFML to be translated to a 4D floating-point vector - public Vec4(Color color) - { - X = color.R / 255.0f; - Y = color.G / 255.0f; - Z = color.B / 255.0f; - W = color.A / 255.0f; - } + /// + /// Construct the from a + /// + /// + /// The 's values will be normalized from 0..255 to 0..1 + /// + /// A SFML to be translated to a 4D floating-point vector + public Vec4(Color color) + { + X = color.R / 255.0f; + Y = color.G / 255.0f; + Z = color.B / 255.0f; + W = color.A / 255.0f; + } - /// Horizontal component of the vector - public float X; + /// Horizontal component of the vector + public float X; - /// Vertical component of the vector - public float Y; + /// Vertical component of the vector + public float Y; - /// Depth component of the vector - public float Z; + /// Depth component of the vector + public float Z; - /// Projective/Homogeneous component of the vector - public float W; - } + /// Projective/Homogeneous component of the vector + public float W; +} +//////////////////////////////////////////////////////////// +/// +/// is a struct represent a glsl ivec4 value +/// +//////////////////////////////////////////////////////////// +[StructLayout(LayoutKind.Sequential)] +public struct Ivec4 +{ //////////////////////////////////////////////////////////// /// - /// is a struct represent a glsl ivec4 value + /// Construct the from its coordinates /// + /// X coordinate + /// Y coordinate + /// Z coordinate + /// W coordinate //////////////////////////////////////////////////////////// - [StructLayout(LayoutKind.Sequential)] - public struct Ivec4 + public Ivec4(int x, int y, int z, int w) { - //////////////////////////////////////////////////////////// - /// - /// Construct the from its coordinates - /// - /// X coordinate - /// Y coordinate - /// Z coordinate - /// W coordinate - //////////////////////////////////////////////////////////// - public Ivec4(int x, int y, int z, int w) - { - X = x; - Y = y; - Z = z; - W = w; - } + X = x; + Y = y; + Z = z; + W = w; + } - /// - /// Construct the from a - /// - /// A SFML to be translated to a 4D integer vector - public Ivec4(Color color) - { - X = color.R; - Y = color.G; - Z = color.B; - W = color.A; - } + /// + /// Construct the from a + /// + /// A SFML to be translated to a 4D integer vector + public Ivec4(Color color) + { + X = color.R; + Y = color.G; + Z = color.B; + W = color.A; + } - /// Horizontal component of the vector - public int X; + /// Horizontal component of the vector + public int X; - /// Vertical component of the vector - public int Y; + /// Vertical component of the vector + public int Y; - /// Depth component of the vector - public int Z; + /// Depth component of the vector + public int Z; - /// Projective/Homogeneous component of the vector - public int W; - } + /// Projective/Homogeneous component of the vector + public int W; +} +//////////////////////////////////////////////////////////// +/// +/// is a struct represent a glsl bvec4 value +/// +//////////////////////////////////////////////////////////// +[StructLayout(LayoutKind.Sequential)] +public struct Bvec4 +{ //////////////////////////////////////////////////////////// /// - /// is a struct represent a glsl bvec4 value + /// Construct the from its coordinates /// + /// X coordinate + /// Y coordinate + /// Z coordinate + /// W coordinate //////////////////////////////////////////////////////////// - [StructLayout(LayoutKind.Sequential)] - public struct Bvec4 + public Bvec4(bool x, bool y, bool z, bool w) { - //////////////////////////////////////////////////////////// - /// - /// Construct the from its coordinates - /// - /// X coordinate - /// Y coordinate - /// Z coordinate - /// W coordinate - //////////////////////////////////////////////////////////// - public Bvec4(bool x, bool y, bool z, bool w) - { - X = x; - Y = y; - Z = z; - W = w; - } + X = x; + Y = y; + Z = z; + W = w; + } - /// Horizontal component of the vector - [MarshalAs(UnmanagedType.I1)] - public bool X; + /// Horizontal component of the vector + [MarshalAs(UnmanagedType.I1)] + public bool X; - /// Vertical component of the vector - [MarshalAs(UnmanagedType.I1)] - public bool Y; + /// Vertical component of the vector + [MarshalAs(UnmanagedType.I1)] + public bool Y; - /// Depth component of the vector - [MarshalAs(UnmanagedType.I1)] - public bool Z; + /// Depth component of the vector + [MarshalAs(UnmanagedType.I1)] + public bool Z; - /// Projective/Homogeneous component of the vector - [MarshalAs(UnmanagedType.I1)] - public bool W; - } - #endregion - - #region Matrices + /// Projective/Homogeneous component of the vector + [MarshalAs(UnmanagedType.I1)] + public bool W; +} +#endregion + +#region Matrices +//////////////////////////////////////////////////////////// +/// +/// is a struct representing a glsl mat3 value +/// +//////////////////////////////////////////////////////////// +[StructLayout(LayoutKind.Sequential)] +public unsafe struct Mat3 +{ //////////////////////////////////////////////////////////// /// - /// is a struct representing a glsl mat3 value + /// Construct the from its components /// + /// + /// + /// Arguments are in row-major order + /// //////////////////////////////////////////////////////////// - [StructLayout(LayoutKind.Sequential)] - public unsafe struct Mat3 + public Mat3(float a00, float a01, float a02, + float a10, float a11, float a12, + float a20, float a21, float a22) { - //////////////////////////////////////////////////////////// - /// - /// Construct the from its components - /// - /// - /// - /// Arguments are in row-major order - /// - //////////////////////////////////////////////////////////// - public Mat3(float a00, float a01, float a02, - float a10, float a11, float a12, - float a20, float a21, float a22) - { - fixed (float* m = _array) - { - m[0] = a00; - m[3] = a01; - m[6] = a02; - m[1] = a10; - m[4] = a11; - m[7] = a12; - m[2] = a20; - m[5] = a21; - m[8] = a22; - } - } - - //////////////////////////////////////////////////////////// - /// - /// Construct the from a SFML - /// - /// A SFML - //////////////////////////////////////////////////////////// - public Mat3(Transform transform) + fixed (float* m = _array) { - fixed (float* m = _array) - { - m[0] = transform.M00; - m[3] = transform.M01; - m[6] = transform.M02; - m[1] = transform.M10; - m[4] = transform.M11; - m[7] = transform.M12; - m[2] = transform.M20; - m[5] = transform.M21; - m[8] = transform.M22; - } + m[0] = a00; + m[3] = a01; + m[6] = a02; + m[1] = a10; + m[4] = a11; + m[7] = a12; + m[2] = a20; + m[5] = a21; + m[8] = a22; } - - // column-major! - private fixed float _array[3 * 3]; } //////////////////////////////////////////////////////////// /// - /// is a struct representing a glsl mat4 value + /// Construct the from a SFML /// + /// A SFML //////////////////////////////////////////////////////////// - [StructLayout(LayoutKind.Sequential)] - public unsafe struct Mat4 + public Mat3(Transform transform) { - //////////////////////////////////////////////////////////// - /// - /// Provides easy-access to an identity matrix - /// - /// - /// - /// Keep in mind that a Mat4 cannot be modified after construction - /// - //////////////////////////////////////////////////////////// - public static Mat4 Identity => new Mat4(1, 0, 0, 0, - 0, 1, 0, 0, - 0, 0, 1, 0, - 0, 0, 0, 1); - - //////////////////////////////////////////////////////////// - /// - /// Construct the from its components - /// - /// - /// - /// Arguments are in row-major order - /// - //////////////////////////////////////////////////////////// - public Mat4(float a00, float a01, float a02, float a03, - float a10, float a11, float a12, float a13, - float a20, float a21, float a22, float a23, - float a30, float a31, float a32, float a33) - { - fixed (float* m = _array) - { - // transpose to column major - m[0] = a00; - m[4] = a01; - m[8] = a02; - m[12] = a03; - m[1] = a10; - m[5] = a11; - m[9] = a12; - m[13] = a13; - m[2] = a20; - m[6] = a21; - m[10] = a22; - m[14] = a23; - m[3] = a30; - m[7] = a31; - m[11] = a32; - m[15] = a33; - } - } + _array[0] = transform.M00; + _array[3] = transform.M01; + _array[6] = transform.M02; + _array[1] = transform.M10; + _array[4] = transform.M11; + _array[7] = transform.M12; + _array[2] = transform.M20; + _array[5] = transform.M21; + _array[8] = transform.M22; + } - //////////////////////////////////////////////////////////// - /// - /// Construct the from a SFML and expand it to a 4x4 matrix - /// - /// A SFML - //////////////////////////////////////////////////////////// - public Mat4(Transform transform) - { - fixed (float* m = _array) - { - // swapping to column-major (OpenGL) from row-major (SFML) order - // in addition, filling in the blanks (from expanding to a mat4) with values from - // an identity matrix - m[0] = transform.M00; - m[4] = transform.M01; - m[8] = 0; - m[12] = transform.M02; - m[1] = transform.M10; - m[5] = transform.M11; - m[9] = 0; - m[13] = transform.M12; - m[2] = 0; - m[6] = 0; - m[10] = 1; - m[14] = 0; - m[3] = transform.M20; - m[7] = transform.M21; - m[11] = 0; - m[15] = transform.M22; - } - } + // column-major! + private fixed float _array[3 * 3]; +} + +//////////////////////////////////////////////////////////// +/// +/// is a struct representing a glsl mat4 value +/// +//////////////////////////////////////////////////////////// +[StructLayout(LayoutKind.Sequential)] +public unsafe struct Mat4 +{ + //////////////////////////////////////////////////////////// + /// + /// Provides easy-access to an identity matrix + /// + /// + /// + /// Keep in mind that a Mat4 cannot be modified after construction + /// + //////////////////////////////////////////////////////////// + public static Mat4 Identity => new(1, 0, 0, 0, + 0, 1, 0, 0, + 0, 0, 1, 0, + 0, 0, 0, 1); + + //////////////////////////////////////////////////////////// + /// + /// Construct the from its components + /// + /// + /// + /// Arguments are in row-major order + /// + //////////////////////////////////////////////////////////// + public Mat4(float a00, float a01, float a02, float a03, + float a10, float a11, float a12, float a13, + float a20, float a21, float a22, float a23, + float a30, float a31, float a32, float a33) + { + // transpose to column major + _array[0] = a00; + _array[4] = a01; + _array[8] = a02; + _array[12] = a03; + _array[1] = a10; + _array[5] = a11; + _array[9] = a12; + _array[13] = a13; + _array[2] = a20; + _array[6] = a21; + _array[10] = a22; + _array[14] = a23; + _array[3] = a30; + _array[7] = a31; + _array[11] = a32; + _array[15] = a33; + } - // column major! - private fixed float _array[4 * 4]; + //////////////////////////////////////////////////////////// + /// + /// Construct the from a SFML and expand it to a 4x4 matrix + /// + /// A SFML + //////////////////////////////////////////////////////////// + public Mat4(Transform transform) + { + // swapping to column-major (OpenGL) from row-major (SFML) order + // in addition, filling in the blanks (from expanding to a mat4) with values from + // an identity matrix + _array[0] = transform.M00; + _array[4] = transform.M01; + _array[8] = 0; + _array[12] = transform.M02; + _array[1] = transform.M10; + _array[5] = transform.M11; + _array[9] = 0; + _array[13] = transform.M12; + _array[2] = 0; + _array[6] = 0; + _array[10] = 1; + _array[14] = 0; + _array[3] = transform.M20; + _array[7] = transform.M21; + _array[11] = 0; + _array[15] = transform.M22; } - #endregion + + // column major! + private fixed float _array[4 * 4]; } +#endregion diff --git a/src/SFML.Graphics/Glyph.cs b/src/SFML.Graphics/Glyph.cs index 5dcc1e6d..85395359 100644 --- a/src/SFML.Graphics/Glyph.cs +++ b/src/SFML.Graphics/Glyph.cs @@ -1,22 +1,21 @@ using System.Runtime.InteropServices; -namespace SFML.Graphics +namespace SFML.Graphics; + +//////////////////////////////////////////////////////////// +/// +/// Structure describing a glyph (a visual character) +/// +//////////////////////////////////////////////////////////// +[StructLayout(LayoutKind.Sequential)] +public struct Glyph { - //////////////////////////////////////////////////////////// - /// - /// Structure describing a glyph (a visual character) - /// - //////////////////////////////////////////////////////////// - [StructLayout(LayoutKind.Sequential)] - public struct Glyph - { - /// Offset to move horizontally to the next character - public float Advance; + /// Offset to move horizontally to the next character + public float Advance; - /// Bounding rectangle of the glyph, in coordinates relative to the baseline - public FloatRect Bounds; + /// Bounding rectangle of the glyph, in coordinates relative to the baseline + public FloatRect Bounds; - /// Texture coordinates of the glyph inside the font's texture - public IntRect TextureRect; - } + /// Texture coordinates of the glyph inside the font's texture + public IntRect TextureRect; } diff --git a/src/SFML.Graphics/IDrawable.cs b/src/SFML.Graphics/IDrawable.cs index dcb86c25..fd96d1f1 100644 --- a/src/SFML.Graphics/IDrawable.cs +++ b/src/SFML.Graphics/IDrawable.cs @@ -1,22 +1,21 @@ -namespace SFML.Graphics +namespace SFML.Graphics; + +//////////////////////////////////////////////////////////// +/// +/// Interface for every object that can be drawn to a render window +/// +//////////////////////////////////////////////////////////// +public interface IDrawable { //////////////////////////////////////////////////////////// /// - /// Interface for every object that can be drawn to a render window + /// Draw the object to a render target + /// + /// This is a function that has to be implemented by the + /// derived class to define how the drawable should be drawn. /// + /// Render target to draw to + /// Current render states //////////////////////////////////////////////////////////// - public interface IDrawable - { - //////////////////////////////////////////////////////////// - /// - /// Draw the object to a render target - /// - /// This is a function that has to be implemented by the - /// derived class to define how the drawable should be drawn. - /// - /// Render target to draw to - /// Current render states - //////////////////////////////////////////////////////////// - void Draw(IRenderTarget target, RenderStates states); - } + public void Draw(IRenderTarget target, RenderStates states); } diff --git a/src/SFML.Graphics/IRenderTarget.cs b/src/SFML.Graphics/IRenderTarget.cs index dffd5fc2..2c5b520d 100644 --- a/src/SFML.Graphics/IRenderTarget.cs +++ b/src/SFML.Graphics/IRenderTarget.cs @@ -1,339 +1,338 @@ using SFML.System; -namespace SFML.Graphics +namespace SFML.Graphics; + +//////////////////////////////////////////////////////////// +/// +/// Interface for render targets. +/// This interface should not be implemented on custom types, use +/// or instead. +/// +//////////////////////////////////////////////////////////// +public interface IRenderTarget { //////////////////////////////////////////////////////////// /// - /// Interface for render targets. - /// This interface should not be implemented on custom types, use - /// or instead. + /// Size of the rendering region of the target /// //////////////////////////////////////////////////////////// - public interface IRenderTarget - { - //////////////////////////////////////////////////////////// - /// - /// Size of the rendering region of the target - /// - //////////////////////////////////////////////////////////// - Vector2u Size { get; } + public Vector2u Size { get; } - //////////////////////////////////////////////////////////// - /// - /// Tell if the render target will use sRGB encoding when drawing on it - /// - //////////////////////////////////////////////////////////// - bool IsSrgb { get; } + //////////////////////////////////////////////////////////// + /// + /// Tell if the render target will use sRGB encoding when drawing on it + /// + //////////////////////////////////////////////////////////// + public bool IsSrgb { get; } - //////////////////////////////////////////////////////////// - /// - /// Default view of the target - /// - //////////////////////////////////////////////////////////// - View DefaultView { get; } + //////////////////////////////////////////////////////////// + /// + /// Default view of the target + /// + //////////////////////////////////////////////////////////// + public View DefaultView { get; } - //////////////////////////////////////////////////////////// - /// - /// Return the current active view - /// - /// The current view - //////////////////////////////////////////////////////////// - View GetView(); + //////////////////////////////////////////////////////////// + /// + /// Return the current active view + /// + /// The current view + //////////////////////////////////////////////////////////// + public View GetView(); - //////////////////////////////////////////////////////////// - /// - /// Change the current active view - /// - /// New view - //////////////////////////////////////////////////////////// - void SetView(View view); + //////////////////////////////////////////////////////////// + /// + /// Change the current active view + /// + /// New view + //////////////////////////////////////////////////////////// + public void SetView(View view); - //////////////////////////////////////////////////////////// - /// - /// Get the viewport of a view applied to this target - /// - /// Target view - /// Viewport rectangle, expressed in pixels in the current target - //////////////////////////////////////////////////////////// - IntRect GetViewport(View view); + //////////////////////////////////////////////////////////// + /// + /// Get the viewport of a view applied to this target + /// + /// Target view + /// Viewport rectangle, expressed in pixels in the current target + //////////////////////////////////////////////////////////// + public IntRect GetViewport(View view); - //////////////////////////////////////////////////////////// - /// - /// 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. - /// - /// The view for which we want to compute the scissor rectangle - /// Scissor rectangle, expressed in pixels - //////////////////////////////////////////////////////////// - IntRect GetScissor(View view); + //////////////////////////////////////////////////////////// + /// + /// 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. + /// + /// The view for which we want to compute the scissor rectangle + /// Scissor rectangle, expressed in pixels + //////////////////////////////////////////////////////////// + public IntRect GetScissor(View view); - //////////////////////////////////////////////////////////// - /// - /// 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: - /// target.MapPixelToCoords(point, target.GetView()); - /// - /// Pixel to convert - /// The converted point, in "world" coordinates - //////////////////////////////////////////////////////////// - Vector2f MapPixelToCoords(Vector2i point); + //////////////////////////////////////////////////////////// + /// + /// 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: + /// target.MapPixelToCoords(point, target.GetView()); + /// + /// Pixel to convert + /// The converted point, in "world" coordinates + //////////////////////////////////////////////////////////// + public Vector2f MapPixelToCoords(Vector2i point); - //////////////////////////////////////////////////////////// - /// - /// 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, ie. 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. - /// - /// Pixel to convert - /// The view to use for converting the point - /// The converted point, in "world" coordinates - //////////////////////////////////////////////////////////// - Vector2f MapPixelToCoords(Vector2i point, View view); + //////////////////////////////////////////////////////////// + /// + /// 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, ie. 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. + /// + /// Pixel to convert + /// The view to use for converting the point + /// The converted point, in "world" coordinates + //////////////////////////////////////////////////////////// + public Vector2f MapPixelToCoords(Vector2i point, View view); - //////////////////////////////////////////////////////////// - /// - /// 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: - /// target.MapCoordsToPixel(point, target.GetView()); - /// - /// Point to convert - /// The converted point, in target coordinates (pixels) - //////////////////////////////////////////////////////////// - Vector2i MapCoordsToPixel(Vector2f point); + //////////////////////////////////////////////////////////// + /// + /// 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: + /// target.MapCoordsToPixel(point, target.GetView()); + /// + /// Point to convert + /// The converted point, in target coordinates (pixels) + //////////////////////////////////////////////////////////// + public Vector2i MapCoordsToPixel(Vector2f point); - //////////////////////////////////////////////////////////// - /// - /// 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, ie. 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. - /// - /// Point to convert - /// The view to use for converting the point - /// The converted point, in target coordinates (pixels) - //////////////////////////////////////////////////////////// - Vector2i MapCoordsToPixel(Vector2f point, View view); + //////////////////////////////////////////////////////////// + /// + /// 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, ie. 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. + /// + /// Point to convert + /// The view to use for converting the point + /// The converted point, in target coordinates (pixels) + //////////////////////////////////////////////////////////// + public Vector2i MapCoordsToPixel(Vector2f point, View view); - //////////////////////////////////////////////////////////// - /// - /// Clear the entire target with black color - /// - //////////////////////////////////////////////////////////// - void Clear(); + //////////////////////////////////////////////////////////// + /// + /// Clear the entire target with black color + /// + //////////////////////////////////////////////////////////// + public void Clear(); - //////////////////////////////////////////////////////////// - /// - /// Clear the entire target with a single color - /// - /// Color to use to clear the window - //////////////////////////////////////////////////////////// - void Clear(Color color); + //////////////////////////////////////////////////////////// + /// + /// Clear the entire target with a single color + /// + /// Color to use to clear the window + //////////////////////////////////////////////////////////// + public void Clear(Color color); - //////////////////////////////////////////////////////////// - /// - /// Clear the stencil buffer to a specific value - /// - /// The specified value is truncated to the bit width of - /// the current stencil buffer. - /// - /// Stencil value to clear to - //////////////////////////////////////////////////////////// - void ClearStencil(StencilValue stencilValue); + //////////////////////////////////////////////////////////// + /// + /// 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. + /// + /// Fill color to use to clear the render target + /// Stencil value to clear to + //////////////////////////////////////////////////////////// + public void Clear(Color color, StencilValue stencilValue); - //////////////////////////////////////////////////////////// - /// - /// 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. - /// - /// Fill color to use to clear the render target - /// Stencil value to clear to - //////////////////////////////////////////////////////////// - void Clear(Color color, StencilValue stencilValue); + //////////////////////////////////////////////////////////// + /// + /// Clear the stencil buffer to a specific value + /// + /// The specified value is truncated to the bit width of + /// the current stencil buffer. + /// + /// Stencil value to clear to + //////////////////////////////////////////////////////////// + public void ClearStencil(StencilValue stencilValue); - //////////////////////////////////////////////////////////// - /// - /// Draw a drawable object to the render-target, with default render states - /// - /// Object to draw - //////////////////////////////////////////////////////////// - void Draw(IDrawable drawable); + //////////////////////////////////////////////////////////// + /// + /// Draw a drawable object to the render-target, with default render states + /// + /// Object to draw + //////////////////////////////////////////////////////////// + public void Draw(IDrawable drawable); - //////////////////////////////////////////////////////////// - /// - /// Draw a drawable object to the render-target - /// - /// Object to draw - /// Render states to use for drawing - //////////////////////////////////////////////////////////// - void Draw(IDrawable drawable, RenderStates states); + //////////////////////////////////////////////////////////// + /// + /// Draw a drawable object to the render-target + /// + /// Object to draw + /// Render states to use for drawing + //////////////////////////////////////////////////////////// + public void Draw(IDrawable drawable, RenderStates states); - //////////////////////////////////////////////////////////// - /// - /// Draw primitives defined by an array of vertices, with default render states - /// - /// Array of vertices to draw - /// Type of primitives to draw - //////////////////////////////////////////////////////////// - void Draw(Vertex[] vertices, PrimitiveType type); + //////////////////////////////////////////////////////////// + /// + /// Draw primitives defined by an array of vertices, with default render states + /// + /// Array of vertices to draw + /// Type of primitives to draw + //////////////////////////////////////////////////////////// + public void Draw(Vertex[] vertices, PrimitiveType type); - //////////////////////////////////////////////////////////// - /// - /// Draw primitives defined by an array of vertices - /// - /// Array of vertices to draw - /// Type of primitives to draw - /// Render states to use for drawing - //////////////////////////////////////////////////////////// - void Draw(Vertex[] vertices, PrimitiveType type, RenderStates states); + //////////////////////////////////////////////////////////// + /// + /// Draw primitives defined by an array of vertices + /// + /// Array of vertices to draw + /// Type of primitives to draw + /// Render states to use for drawing + //////////////////////////////////////////////////////////// + public void Draw(Vertex[] vertices, PrimitiveType type, RenderStates states); - //////////////////////////////////////////////////////////// - /// - /// Draw primitives defined by a sub-array of vertices, with default render states - /// - /// Array of vertices to draw - /// Index of the first vertex to draw in the array - /// Number of vertices to draw - /// Type of primitives to draw - //////////////////////////////////////////////////////////// - void Draw(Vertex[] vertices, uint start, uint count, PrimitiveType type); + //////////////////////////////////////////////////////////// + /// + /// Draw primitives defined by a sub-array of vertices, with default render states + /// + /// Array of vertices to draw + /// Index of the first vertex to draw in the array + /// Number of vertices to draw + /// Type of primitives to draw + //////////////////////////////////////////////////////////// + public void Draw(Vertex[] vertices, uint start, uint count, PrimitiveType type); - //////////////////////////////////////////////////////////// - /// - /// Draw primitives defined by a sub-array of vertices - /// - /// Pointer to the vertices - /// Index of the first vertex to use in the array - /// Number of vertices to draw - /// Type of primitives to draw - /// Render states to use for drawing - //////////////////////////////////////////////////////////// - void Draw(Vertex[] vertices, uint start, uint count, PrimitiveType type, RenderStates states); + //////////////////////////////////////////////////////////// + /// + /// Draw primitives defined by a sub-array of vertices + /// + /// Pointer to the vertices + /// Index of the first vertex to use in the array + /// Number of vertices to draw + /// Type of primitives to draw + /// Render states to use for drawing + //////////////////////////////////////////////////////////// + public void Draw(Vertex[] vertices, uint start, uint count, PrimitiveType type, RenderStates states); - //////////////////////////////////////////////////////////// - /// - /// 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). - /// - /// True to activate, false to deactivate - /// True if operation was successful, false otherwise - //////////////////////////////////////////////////////////// - bool SetActive(bool active); + //////////////////////////////////////////////////////////// + /// + /// 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). + /// + /// True to activate, false to deactivate + /// True if operation was successful, false otherwise + //////////////////////////////////////////////////////////// + public bool SetActive(bool active); - //////////////////////////////////////////////////////////// - /// - /// 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: - /// - /// // OpenGL code here... - /// window.PushGLStates(); - /// window.Draw(...); - /// window.Draw(...); - /// window.PopGLStates(); - /// // OpenGL code here... - /// - /// 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. - /// - //////////////////////////////////////////////////////////// - void PushGLStates(); + //////////////////////////////////////////////////////////// + /// + /// 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: + /// + /// // OpenGL code here... + /// window.PushGLStates(); + /// window.Draw(...); + /// window.Draw(...); + /// window.PopGLStates(); + /// // OpenGL code here... + /// + /// 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. + /// + //////////////////////////////////////////////////////////// + public void PushGLStates(); - //////////////////////////////////////////////////////////// - /// - /// Restore the previously saved OpenGL render states and matrices. - /// - /// See the description of PushGLStates to get a detailed - /// description of these functions. - /// - //////////////////////////////////////////////////////////// - void PopGLStates(); + //////////////////////////////////////////////////////////// + /// + /// Restore the previously saved OpenGL render states and matrices. + /// + /// See the description of PushGLStates to get a detailed + /// description of these functions. + /// + //////////////////////////////////////////////////////////// + public void PopGLStates(); - //////////////////////////////////////////////////////////// - /// - /// 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: - /// - /// // OpenGL code here... - /// glPushAttrib(...); - /// window.ResetGLStates(); - /// window.Draw(...); - /// window.Draw(...); - /// glPopAttrib(...); - /// // OpenGL code here... - /// - //////////////////////////////////////////////////////////// - void ResetGLStates(); - } + //////////////////////////////////////////////////////////// + /// + /// 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: + /// + /// // OpenGL code here... + /// glPushAttrib(...); + /// window.ResetGLStates(); + /// window.Draw(...); + /// window.Draw(...); + /// glPopAttrib(...); + /// // OpenGL code here... + /// + //////////////////////////////////////////////////////////// + public void ResetGLStates(); } diff --git a/src/SFML.Graphics/Image.cs b/src/SFML.Graphics/Image.cs index 9421e3ee..e1b6f018 100644 --- a/src/SFML.Graphics/Image.cs +++ b/src/SFML.Graphics/Image.cs @@ -4,402 +4,399 @@ using System.Security; using SFML.System; -namespace SFML.Graphics +namespace SFML.Graphics; + +//////////////////////////////////////////////////////////// +/// +/// Image is the low-level class for loading and +/// manipulating images +/// +//////////////////////////////////////////////////////////// +public class Image : ObjectBase { //////////////////////////////////////////////////////////// /// - /// Image is the low-level class for loading and - /// manipulating images + /// Construct the image with black color /// + /// Width and height of the image + /// //////////////////////////////////////////////////////////// - public class Image : ObjectBase + public Image(Vector2u size) : this(size, Color.Black) { } + + //////////////////////////////////////////////////////////// + /// + /// Construct the image from a single color + /// + /// Width and height of the image + /// Color to fill the image with + /// + //////////////////////////////////////////////////////////// + public Image(Vector2u size, Color color) : base(sfImage_createFromColor(size, color)) { - //////////////////////////////////////////////////////////// - /// - /// Construct the image with black color - /// - /// Width and height of the image - /// - //////////////////////////////////////////////////////////// - public Image(Vector2u size) : this(size, Color.Black) { } - - //////////////////////////////////////////////////////////// - /// - /// Construct the image from a single color - /// - /// Width and height of the image - /// Color to fill the image with - /// - //////////////////////////////////////////////////////////// - public Image(Vector2u size, Color color) : base(sfImage_createFromColor(size, color)) + if (IsInvalid) { - if (IsInvalid) - { - throw new LoadingFailedException("image"); - } + throw new LoadingFailedException("image"); } + } - //////////////////////////////////////////////////////////// - /// - /// Construct the image from a file - /// - /// Path of the image file to load - /// - //////////////////////////////////////////////////////////// - public Image(string filename) : base(sfImage_createFromFile(filename)) + //////////////////////////////////////////////////////////// + /// + /// Construct the image from a file + /// + /// Path of the image file to load + /// + //////////////////////////////////////////////////////////// + public Image(string filename) : base(sfImage_createFromFile(filename)) + { + if (IsInvalid) { - if (IsInvalid) - { - throw new LoadingFailedException("image", filename); - } + throw new LoadingFailedException("image", filename); } + } - //////////////////////////////////////////////////////////// - /// - /// Construct the image from a file in a stream - /// - /// Stream containing the file contents - /// - //////////////////////////////////////////////////////////// - public Image(Stream stream) : - base(IntPtr.Zero) + //////////////////////////////////////////////////////////// + /// + /// Construct the image from a file in a stream + /// + /// Stream containing the file contents + /// + //////////////////////////////////////////////////////////// + public Image(Stream stream) : + base(IntPtr.Zero) + { + using (var adaptor = new SFML.System.StreamAdaptor(stream)) { - using (var adaptor = new SFML.System.StreamAdaptor(stream)) - { - CPointer = sfImage_createFromStream(adaptor.InputStreamPtr); - } - - if (IsInvalid) - { - throw new LoadingFailedException("image"); - } + CPointer = sfImage_createFromStream(adaptor.InputStreamPtr); } - //////////////////////////////////////////////////////////// - /// - /// Construct the image from a file in memory - /// - /// Byte array containing the file contents - /// - //////////////////////////////////////////////////////////// - public Image(byte[] bytes) : - base(IntPtr.Zero) + if (IsInvalid) { - unsafe - { - fixed (void* ptr = bytes) - { - CPointer = sfImage_createFromMemory((IntPtr)ptr, (UIntPtr)bytes.Length); - } - } + throw new LoadingFailedException("image"); + } + } - if (IsInvalid) + //////////////////////////////////////////////////////////// + /// + /// Construct the image from a file in memory + /// + /// Byte array containing the file contents + /// + //////////////////////////////////////////////////////////// + public Image(byte[] bytes) : + base(IntPtr.Zero) + { + unsafe + { + fixed (void* ptr = bytes) { - throw new LoadingFailedException("image"); + CPointer = sfImage_createFromMemory((IntPtr)ptr, (UIntPtr)bytes.Length); } } - //////////////////////////////////////////////////////////// - /// - /// Construct the image directly from an array of pixels - /// - /// 2 dimensions array containing the pixels - /// - //////////////////////////////////////////////////////////// - public Image(Color[,] pixels) : - base(IntPtr.Zero) + if (IsInvalid) { - var width = (uint)pixels.GetLength(0); - var height = (uint)pixels.GetLength(1); - - // Transpose the array (.Net gives dimensions in reverse order of what SFML expects) - var transposed = new Color[height, width]; - for (var x = 0; x < width; ++x) - { - for (var y = 0; y < height; ++y) - { - transposed[y, x] = pixels[x, y]; - } - } + throw new LoadingFailedException("image"); + } + } - unsafe - { - fixed (Color* pixelsPtr = transposed) - { - CPointer = sfImage_createFromPixels(new Vector2u(width, height), (byte*)pixelsPtr); - } - } + //////////////////////////////////////////////////////////// + /// + /// Construct the image directly from an array of pixels + /// + /// 2 dimensions array containing the pixels + /// + //////////////////////////////////////////////////////////// + public Image(Color[,] pixels) : + base(IntPtr.Zero) + { + var width = (uint)pixels.GetLength(0); + var height = (uint)pixels.GetLength(1); - if (IsInvalid) + // Transpose the array (.Net gives dimensions in reverse order of what SFML expects) + var transposed = new Color[height, width]; + for (var x = 0; x < width; ++x) + { + for (var y = 0; y < height; ++y) { - throw new LoadingFailedException("image"); + transposed[y, x] = pixels[x, y]; } } - //////////////////////////////////////////////////////////// - /// - /// Construct the image directly from an array of pixels - /// - /// Width and height of the image - /// array containing the pixels - /// - //////////////////////////////////////////////////////////// - public Image(Vector2u size, byte[] pixels) : - base(IntPtr.Zero) + unsafe { - unsafe - { - fixed (byte* pixelsPtr = pixels) - { - CPointer = sfImage_createFromPixels(size, pixelsPtr); - } - } - - if (IsInvalid) + fixed (Color* pixelsPtr = transposed) { - throw new LoadingFailedException("image"); + CPointer = sfImage_createFromPixels(new Vector2u(width, height), (byte*)pixelsPtr); } } - //////////////////////////////////////////////////////////// - /// - /// Construct the image from another image - /// - /// Image to copy - //////////////////////////////////////////////////////////// - public Image(Image copy) : - base(sfImage_copy(copy.CPointer)) + if (IsInvalid) { + throw new LoadingFailedException("image"); } + } - //////////////////////////////////////////////////////////// - /// - /// Save the contents of the image to a file - /// - /// Path of the file to save (overwritten if already exist) - /// True if saving was successful - //////////////////////////////////////////////////////////// - public bool SaveToFile(string filename) => sfImage_saveToFile(CPointer, filename); - - //////////////////////////////////////////////////////////// - /// - /// 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. - /// - /// Byte array filled with encoded data - /// Encoding format to use - /// True if saving was successful - //////////////////////////////////////////////////////////// - public bool SaveToMemory(out byte[] output, string format) + //////////////////////////////////////////////////////////// + /// + /// Construct the image directly from an array of pixels + /// + /// Width and height of the image + /// array containing the pixels + /// + //////////////////////////////////////////////////////////// + public Image(Vector2u size, byte[] pixels) : + base(IntPtr.Zero) + { + unsafe { - using (var buffer = new SFML.System.Buffer()) + fixed (byte* pixelsPtr = pixels) { - var success = sfImage_saveToMemory(CPointer, buffer.CPointer, format); - - output = success ? buffer.GetData() : Array.Empty(); - return success; + CPointer = sfImage_createFromPixels(size, pixelsPtr); } } - //////////////////////////////////////////////////////////// - /// - /// Create a transparency mask from a specified colorkey - /// - /// Color to become transparent - //////////////////////////////////////////////////////////// - public void CreateMaskFromColor(Color color) => CreateMaskFromColor(color, 0); - - //////////////////////////////////////////////////////////// - /// - /// Create a transparency mask from a specified colorkey - /// - /// Color to become transparent - /// Alpha value to use for transparent pixels - //////////////////////////////////////////////////////////// - public void CreateMaskFromColor(Color color, byte alpha) => sfImage_createMaskFromColor(CPointer, color, alpha); - - //////////////////////////////////////////////////////////// - /// - /// Copy pixels from another image onto this one. - /// This function does a slow pixel copy and should only - /// be used at initialization time - /// - /// Source image to copy - /// Coordinates of the destination position - //////////////////////////////////////////////////////////// - public void Copy(Image source, Vector2u dest) => Copy(source, dest, new IntRect((0, 0), (0, 0))); - - //////////////////////////////////////////////////////////// - /// - /// Copy pixels from another image onto this one. - /// This function does a slow pixel copy and should only - /// be used at initialization time - /// - /// Source image to copy - /// Coordinates of the destination position - /// Sub-rectangle of the source image to copy - //////////////////////////////////////////////////////////// - public void Copy(Image source, Vector2u dest, IntRect sourceRect) => Copy(source, dest, sourceRect, false); - - //////////////////////////////////////////////////////////// - /// - /// Copy pixels from another image onto this one. - /// This function does a slow pixel copy and should only - /// be used at initialization time - /// - /// Source image to copy - /// Coordinates of the destination position - /// Sub-rectangle of the source image to copy - /// Should the copy take in account the source transparency? - //////////////////////////////////////////////////////////// - public void Copy(Image source, Vector2u dest, IntRect sourceRect, bool applyAlpha) => sfImage_copyImage(CPointer, source.CPointer, dest, sourceRect, applyAlpha); - - //////////////////////////////////////////////////////////// - /// - /// Get a pixel from the image - /// - /// Coordinates of pixel to change - /// Color of pixel (x, y) - //////////////////////////////////////////////////////////// - public Color GetPixel(Vector2u coords) => sfImage_getPixel(CPointer, coords); - - //////////////////////////////////////////////////////////// - /// - /// Change the color of a pixel - /// - /// Coordinates of pixel to change - /// New color for pixel (x, y) - //////////////////////////////////////////////////////////// - public void SetPixel(Vector2u coords, Color color) => sfImage_setPixel(CPointer, coords, color); - - //////////////////////////////////////////////////////////// - /// - /// Get a copy of the array of pixels (RGBA 8 bits integers components) - /// Array size is Width x Height x 4 - /// - /// Array of pixels - //////////////////////////////////////////////////////////// - public byte[] Pixels + if (IsInvalid) { - get - { - var size = Size; - var pixelsPtr = new byte[size.X * size.Y * 4]; - Marshal.Copy(sfImage_getPixelsPtr(CPointer), pixelsPtr, 0, pixelsPtr.Length); - return pixelsPtr; - } + throw new LoadingFailedException("image"); } + } + + //////////////////////////////////////////////////////////// + /// + /// Construct the image from another image + /// + /// Image to copy + //////////////////////////////////////////////////////////// + public Image(Image copy) : + base(sfImage_copy(copy.CPointer)) + { + } + + //////////////////////////////////////////////////////////// + /// + /// Save the contents of the image to a file + /// + /// Path of the file to save (overwritten if already exist) + /// True if saving was successful + //////////////////////////////////////////////////////////// + public bool SaveToFile(string filename) => sfImage_saveToFile(CPointer, filename); + + //////////////////////////////////////////////////////////// + /// + /// 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. + /// + /// Byte array filled with encoded data + /// Encoding format to use + /// True if saving was successful + //////////////////////////////////////////////////////////// + public bool SaveToMemory(out byte[] output, string format) + { + using var buffer = new SFML.System.Buffer(); + var success = sfImage_saveToMemory(CPointer, buffer.CPointer, format); + + output = success ? buffer.GetData() : []; + return success; + } + + //////////////////////////////////////////////////////////// + /// + /// Create a transparency mask from a specified colorkey + /// + /// Color to become transparent + //////////////////////////////////////////////////////////// + public void CreateMaskFromColor(Color color) => CreateMaskFromColor(color, 0); + + //////////////////////////////////////////////////////////// + /// + /// Create a transparency mask from a specified colorkey + /// + /// Color to become transparent + /// Alpha value to use for transparent pixels + //////////////////////////////////////////////////////////// + public void CreateMaskFromColor(Color color, byte alpha) => sfImage_createMaskFromColor(CPointer, color, alpha); + + //////////////////////////////////////////////////////////// + /// + /// Copy pixels from another image onto this one. + /// This function does a slow pixel copy and should only + /// be used at initialization time + /// + /// Source image to copy + /// Coordinates of the destination position + //////////////////////////////////////////////////////////// + public void Copy(Image source, Vector2u dest) => Copy(source, dest, new IntRect((0, 0), (0, 0))); + + //////////////////////////////////////////////////////////// + /// + /// Copy pixels from another image onto this one. + /// This function does a slow pixel copy and should only + /// be used at initialization time + /// + /// Source image to copy + /// Coordinates of the destination position + /// Sub-rectangle of the source image to copy + //////////////////////////////////////////////////////////// + public void Copy(Image source, Vector2u dest, IntRect sourceRect) => Copy(source, dest, sourceRect, false); + + //////////////////////////////////////////////////////////// + /// + /// Copy pixels from another image onto this one. + /// This function does a slow pixel copy and should only + /// be used at initialization time + /// + /// Source image to copy + /// Coordinates of the destination position + /// Sub-rectangle of the source image to copy + /// Should the copy take in account the source transparency? + //////////////////////////////////////////////////////////// + public void Copy(Image source, Vector2u dest, IntRect sourceRect, bool applyAlpha) => sfImage_copyImage(CPointer, source.CPointer, dest, sourceRect, applyAlpha); + + //////////////////////////////////////////////////////////// + /// + /// Get a pixel from the image + /// + /// Coordinates of pixel to change + /// Color of pixel (x, y) + //////////////////////////////////////////////////////////// + public Color GetPixel(Vector2u coords) => sfImage_getPixel(CPointer, coords); + + //////////////////////////////////////////////////////////// + /// + /// Change the color of a pixel + /// + /// Coordinates of pixel to change + /// New color for pixel (x, y) + //////////////////////////////////////////////////////////// + public void SetPixel(Vector2u coords, Color color) => sfImage_setPixel(CPointer, coords, color); - //////////////////////////////////////////////////////////// - /// - /// Size of the image, in pixels - /// - //////////////////////////////////////////////////////////// - public Vector2u Size => sfImage_getSize(CPointer); - - //////////////////////////////////////////////////////////// - /// - /// Flip the image horizontally - /// - //////////////////////////////////////////////////////////// - public void FlipHorizontally() => sfImage_flipHorizontally(CPointer); - - //////////////////////////////////////////////////////////// - /// - /// Flip the image vertically - /// - //////////////////////////////////////////////////////////// - public void FlipVertically() => sfImage_flipVertically(CPointer); - - //////////////////////////////////////////////////////////// - /// - /// Provide a string describing the object - /// - /// String description of the object - //////////////////////////////////////////////////////////// - public override string ToString() + //////////////////////////////////////////////////////////// + /// + /// Get a copy of the array of pixels (RGBA 8 bits integers components) + /// Array size is Width x Height x 4 + /// + /// Array of pixels + //////////////////////////////////////////////////////////// + public byte[] Pixels + { + get { - if (IsInvalid) - { - return MakeDisposedObjectString(); - } + var size = Size; + var pixelsPtr = new byte[size.X * size.Y * 4]; + Marshal.Copy(sfImage_getPixelsPtr(CPointer), pixelsPtr, 0, pixelsPtr.Length); + return pixelsPtr; + } + } + + //////////////////////////////////////////////////////////// + /// + /// Size of the image, in pixels + /// + //////////////////////////////////////////////////////////// + public Vector2u Size => sfImage_getSize(CPointer); + + //////////////////////////////////////////////////////////// + /// + /// Flip the image horizontally + /// + //////////////////////////////////////////////////////////// + public void FlipHorizontally() => sfImage_flipHorizontally(CPointer); - return $"[Image] Size({Size})"; + //////////////////////////////////////////////////////////// + /// + /// Flip the image vertically + /// + //////////////////////////////////////////////////////////// + public void FlipVertically() => sfImage_flipVertically(CPointer); + + //////////////////////////////////////////////////////////// + /// + /// Provide a string describing the object + /// + /// String description of the object + //////////////////////////////////////////////////////////// + public override string ToString() + { + if (IsInvalid) + { + return MakeDisposedObjectString(); } - //////////////////////////////////////////////////////////// - /// - /// Internal constructor - /// - /// Pointer to the object in C library - //////////////////////////////////////////////////////////// - internal Image(IntPtr cPointer) : base(cPointer) { } + return $"[Image] Size({Size})"; + } - //////////////////////////////////////////////////////////// - /// - /// Handle the destruction of the object - /// - /// Is the GC disposing the object, or is it an explicit call ? - //////////////////////////////////////////////////////////// - protected override void Destroy(bool disposing) => sfImage_destroy(CPointer); + //////////////////////////////////////////////////////////// + /// + /// Internal constructor + /// + /// Pointer to the object in C library + //////////////////////////////////////////////////////////// + internal Image(IntPtr cPointer) : base(cPointer) { } - #region Imports - [DllImport(CSFML.Graphics, CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] - private static extern IntPtr sfImage_createFromColor(Vector2u size, Color col); + //////////////////////////////////////////////////////////// + /// + /// Handle the destruction of the object + /// + /// Is the GC disposing the object, or is it an explicit call ? + //////////////////////////////////////////////////////////// + protected override void Destroy(bool disposing) => sfImage_destroy(CPointer); - [DllImport(CSFML.Graphics, CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] - private static extern unsafe IntPtr sfImage_createFromPixels(Vector2u size, byte* pixels); + #region Imports + [DllImport(CSFML.Graphics, CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] + private static extern IntPtr sfImage_createFromColor(Vector2u size, Color col); - [DllImport(CSFML.Graphics, CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] - private static extern IntPtr sfImage_createFromFile(string filename); + [DllImport(CSFML.Graphics, CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] + private static extern unsafe IntPtr sfImage_createFromPixels(Vector2u size, byte* pixels); - [DllImport(CSFML.Graphics, CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] - private static extern unsafe IntPtr sfImage_createFromStream(IntPtr stream); + [DllImport(CSFML.Graphics, CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] + private static extern IntPtr sfImage_createFromFile(string filename); - [DllImport(CSFML.Graphics, CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] - private static extern unsafe IntPtr sfImage_createFromMemory(IntPtr data, UIntPtr size); + [DllImport(CSFML.Graphics, CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] + private static extern IntPtr sfImage_createFromStream(IntPtr stream); - [DllImport(CSFML.Graphics, CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] - private static extern IntPtr sfImage_copy(IntPtr image); + [DllImport(CSFML.Graphics, CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] + private static extern IntPtr sfImage_createFromMemory(IntPtr data, UIntPtr size); - [DllImport(CSFML.Graphics, CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] - private static extern void sfImage_destroy(IntPtr cPointer); + [DllImport(CSFML.Graphics, CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] + private static extern IntPtr sfImage_copy(IntPtr image); - [DllImport(CSFML.Graphics, CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] - [return: MarshalAs(UnmanagedType.I1)] - private static extern bool sfImage_saveToFile(IntPtr cPointer, string filename); + [DllImport(CSFML.Graphics, CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] + private static extern void sfImage_destroy(IntPtr cPointer); - [DllImport(CSFML.Graphics, CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] - [return: MarshalAs(UnmanagedType.I1)] - private static extern bool sfImage_saveToMemory(IntPtr cPointer, IntPtr bufferOutput, string format); + [DllImport(CSFML.Graphics, CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] + [return: MarshalAs(UnmanagedType.I1)] + private static extern bool sfImage_saveToFile(IntPtr cPointer, string filename); - [DllImport(CSFML.Graphics, CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] - private static extern void sfImage_createMaskFromColor(IntPtr cPointer, Color col, byte alpha); + [DllImport(CSFML.Graphics, CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] + [return: MarshalAs(UnmanagedType.I1)] + private static extern bool sfImage_saveToMemory(IntPtr cPointer, IntPtr bufferOutput, string format); - [DllImport(CSFML.Graphics, CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] - private static extern void sfImage_copyImage(IntPtr cPointer, IntPtr source, Vector2u dest, IntRect sourceRect, bool applyAlpha); + [DllImport(CSFML.Graphics, CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] + private static extern void sfImage_createMaskFromColor(IntPtr cPointer, Color col, byte alpha); - [DllImport(CSFML.Graphics, CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] - private static extern void sfImage_setPixel(IntPtr cPointer, Vector2u coords, Color col); + [DllImport(CSFML.Graphics, CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] + private static extern void sfImage_copyImage(IntPtr cPointer, IntPtr source, Vector2u dest, IntRect sourceRect, bool applyAlpha); - [DllImport(CSFML.Graphics, CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] - private static extern Color sfImage_getPixel(IntPtr cPointer, Vector2u coords); + [DllImport(CSFML.Graphics, CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] + private static extern void sfImage_setPixel(IntPtr cPointer, Vector2u coords, Color col); - [DllImport(CSFML.Graphics, CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] - private static extern IntPtr sfImage_getPixelsPtr(IntPtr cPointer); + [DllImport(CSFML.Graphics, CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] + private static extern Color sfImage_getPixel(IntPtr cPointer, Vector2u coords); - [DllImport(CSFML.Graphics, CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] - private static extern Vector2u sfImage_getSize(IntPtr cPointer); + [DllImport(CSFML.Graphics, CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] + private static extern IntPtr sfImage_getPixelsPtr(IntPtr cPointer); - [DllImport(CSFML.Graphics, CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] - private static extern void sfImage_flipHorizontally(IntPtr cPointer); + [DllImport(CSFML.Graphics, CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] + private static extern Vector2u sfImage_getSize(IntPtr cPointer); - [DllImport(CSFML.Graphics, CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] - private static extern void sfImage_flipVertically(IntPtr cPointer); - #endregion - } + [DllImport(CSFML.Graphics, CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] + private static extern void sfImage_flipHorizontally(IntPtr cPointer); + + [DllImport(CSFML.Graphics, CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] + private static extern void sfImage_flipVertically(IntPtr cPointer); + #endregion } diff --git a/src/SFML.Graphics/PrimitiveType.cs b/src/SFML.Graphics/PrimitiveType.cs index c2f68e4e..b023d7a6 100644 --- a/src/SFML.Graphics/PrimitiveType.cs +++ b/src/SFML.Graphics/PrimitiveType.cs @@ -1,34 +1,33 @@ -namespace SFML.Graphics +namespace SFML.Graphics; + +//////////////////////////////////////////////////////////// +/// +/// Types of primitives that a or can render. +/// +/// +/// +/// Points and lines have no area, therefore their thickness +/// will always be 1 pixel, regardless the current transform +/// and view. +/// +//////////////////////////////////////////////////////////// +public enum PrimitiveType { - //////////////////////////////////////////////////////////// - /// - /// Types of primitives that a or can render. - /// - /// - /// - /// Points and lines have no area, therefore their thickness - /// will always be 1 pixel, regardless the current transform - /// and view. - /// - //////////////////////////////////////////////////////////// - public enum PrimitiveType - { - /// Individual Points - Points, + /// Individual Points + Points, - /// Individual, Disconnected Lines; each pair of points forms a line - Lines, + /// Individual, Disconnected Lines; each pair of points forms a line + Lines, - /// Connected Lines; each point starts at the previous point to form a line - LineStrip, + /// Connected Lines; each point starts at the previous point to form a line + LineStrip, - /// Individual, Disconnected Triangles - Triangles, + /// Individual, Disconnected Triangles + Triangles, - /// Connected Triangles; each point uses the two previous points to form a triangle - TriangleStrip, + /// Connected Triangles; each point uses the two previous points to form a triangle + TriangleStrip, - /// Connected Triangles; each point uses the first point and the previous point to form a triangle - TriangleFan - } + /// Connected Triangles; each point uses the first point and the previous point to form a triangle + TriangleFan } diff --git a/src/SFML.Graphics/Rect.cs b/src/SFML.Graphics/Rect.cs index 61fe5a1d..24453de1 100644 --- a/src/SFML.Graphics/Rect.cs +++ b/src/SFML.Graphics/Rect.cs @@ -2,428 +2,425 @@ using System.Runtime.InteropServices; using SFML.System; -namespace SFML.Graphics +namespace SFML.Graphics; + +//////////////////////////////////////////////////////////// +/// +/// IntRect is an utility class for manipulating 2D rectangles +/// with integer coordinates +/// +//////////////////////////////////////////////////////////// +[StructLayout(LayoutKind.Sequential)] +public struct IntRect : IEquatable { //////////////////////////////////////////////////////////// /// - /// IntRect is an utility class for manipulating 2D rectangles - /// with integer coordinates + /// Construct the rectangle from position and size /// + /// Position of the top-left corner of the rectangle + /// Size of the rectangle //////////////////////////////////////////////////////////// - [StructLayout(LayoutKind.Sequential)] - public struct IntRect : IEquatable + public IntRect(Vector2i position, Vector2i size) { - //////////////////////////////////////////////////////////// - /// - /// Construct the rectangle from position and size - /// - /// Position of the top-left corner of the rectangle - /// Size of the rectangle - //////////////////////////////////////////////////////////// - public IntRect(Vector2i position, Vector2i size) - { - Position = position; - Size = size; - } + Position = position; + Size = size; + } - //////////////////////////////////////////////////////////// - /// - /// Check if a point is inside the rectangle's area - /// - /// Point to test - /// True if the point is inside - //////////////////////////////////////////////////////////// - public bool Contains(Vector2i point) - { - var minX = Math.Min(Left, Left + Width); - var maxX = Math.Max(Left, Left + Width); - var minY = Math.Min(Top, Top + Height); - var maxY = Math.Max(Top, Top + Height); - - return - (point.X >= minX) && (point.X < maxX) && - (point.Y >= minY) && (point.Y < maxY); - } + //////////////////////////////////////////////////////////// + /// + /// Check if a point is inside the rectangle's area + /// + /// Point to test + /// True if the point is inside + //////////////////////////////////////////////////////////// + public readonly bool Contains(Vector2i point) + { + var minX = Math.Min(Left, Left + Width); + var maxX = Math.Max(Left, Left + Width); + var minY = Math.Min(Top, Top + Height); + var maxY = Math.Max(Top, Top + Height); + + return + point.X >= minX && point.X < maxX && + point.Y >= minY && point.Y < maxY; + } + + //////////////////////////////////////////////////////////// + /// + /// Check if a point is inside the rectangle's area + /// + /// Vector2 position of the point to test + /// True if the point is inside + //////////////////////////////////////////////////////////// + public readonly bool Contains(Vector2u point) => Contains((Vector2i)point); - //////////////////////////////////////////////////////////// - /// - /// Check if a point is inside the rectangle's area - /// - /// Vector2 position of the point to test - /// True if the point is inside - //////////////////////////////////////////////////////////// - public bool Contains(Vector2u point) => Contains((Vector2i)point); - - //////////////////////////////////////////////////////////// - /// - /// Check if a point is inside the rectangle's area - /// - /// Vector2 position of the point to test - /// True if the point is inside - //////////////////////////////////////////////////////////// - public bool Contains(Vector2f point) => Contains((Vector2i)point); - - //////////////////////////////////////////////////////////// - /// - /// Check the intersection between two rectangles - /// - /// Rectangle to test - /// Intersection rectangle if intersecting, null otherwise - //////////////////////////////////////////////////////////// - public IntRect? FindIntersection(IntRect rect) + //////////////////////////////////////////////////////////// + /// + /// Check if a point is inside the rectangle's area + /// + /// Vector2 position of the point to test + /// True if the point is inside + //////////////////////////////////////////////////////////// + public readonly bool Contains(Vector2f point) => Contains((Vector2i)point); + + //////////////////////////////////////////////////////////// + /// + /// Check the intersection between two rectangles + /// + /// Rectangle to test + /// Intersection rectangle if intersecting, null otherwise + //////////////////////////////////////////////////////////// + public readonly IntRect? FindIntersection(IntRect rect) + { + // Rectangles with negative dimensions are allowed, so we must handle them correctly + + // Compute the min and max of the first rectangle on both axes + var r1MinX = Math.Min(Left, Left + Width); + var r1MaxX = Math.Max(Left, Left + Width); + var r1MinY = Math.Min(Top, Top + Height); + var r1MaxY = Math.Max(Top, Top + Height); + + // Compute the min and max of the second rectangle on both axes + var r2MinX = Math.Min(rect.Left, rect.Left + rect.Width); + var r2MaxX = Math.Max(rect.Left, rect.Left + rect.Width); + var r2MinY = Math.Min(rect.Top, rect.Top + rect.Height); + var r2MaxY = Math.Max(rect.Top, rect.Top + rect.Height); + + // Compute the intersection boundaries + var interLeft = Math.Max(r1MinX, r2MinX); + var interTop = Math.Max(r1MinY, r2MinY); + var interRight = Math.Min(r1MaxX, r2MaxX); + var interBottom = Math.Min(r1MaxY, r2MaxY); + + // If the intersection is valid (positive non zero area), then there is an intersection + if (interLeft < interRight && interTop < interBottom) { - // Rectangles with negative dimensions are allowed, so we must handle them correctly - - // Compute the min and max of the first rectangle on both axes - var r1MinX = Math.Min(Left, Left + Width); - var r1MaxX = Math.Max(Left, Left + Width); - var r1MinY = Math.Min(Top, Top + Height); - var r1MaxY = Math.Max(Top, Top + Height); - - // Compute the min and max of the second rectangle on both axes - var r2MinX = Math.Min(rect.Left, rect.Left + rect.Width); - var r2MaxX = Math.Max(rect.Left, rect.Left + rect.Width); - var r2MinY = Math.Min(rect.Top, rect.Top + rect.Height); - var r2MaxY = Math.Max(rect.Top, rect.Top + rect.Height); - - // Compute the intersection boundaries - var interLeft = Math.Max(r1MinX, r2MinX); - var interTop = Math.Max(r1MinY, r2MinY); - var interRight = Math.Min(r1MaxX, r2MaxX); - var interBottom = Math.Min(r1MaxY, r2MaxY); - - // If the intersection is valid (positive non zero area), then there is an intersection - if ((interLeft < interRight) && (interTop < interBottom)) - { - return new IntRect((interLeft, interTop), (interRight - interLeft, interBottom - interTop)); - } - else - { - return null; - } + return new IntRect((interLeft, interTop), (interRight - interLeft, interBottom - interTop)); } - - /// - /// Deconstructs an IntRect into a tuple of ints - /// - /// Left coordinate of the rectangle - /// Top coordinate of the rectangle - /// Width of the rectangle - /// Height of the rectangle - public void Deconstruct(out int left, out int top, out int width, out int height) + else { - left = Position.X; - top = Position.Y; - width = Size.X; - height = Size.Y; + return null; } + } - //////////////////////////////////////////////////////////// - /// - /// Provide a string describing the object - /// - /// String description of the object - //////////////////////////////////////////////////////////// - public override string ToString() => $"[IntRect] Position({Left}, {Top}) Size({Width}, {Height})"; - - //////////////////////////////////////////////////////////// - /// - /// Compare rectangle and object and checks if they are equal - /// - /// Object to check - /// Object and rectangle are equal - //////////////////////////////////////////////////////////// - public override bool Equals(object obj) => (obj is IntRect rect) && Equals(rect); - - /////////////////////////////////////////////////////////// - /// - /// Compare two rectangles and checks if they are equal - /// - /// Rectangle to check - /// Rectangles are equal - //////////////////////////////////////////////////////////// - public bool Equals(IntRect other) => (Left == other.Left) && - (Top == other.Top) && - (Width == other.Width) && - (Height == other.Height); - - //////////////////////////////////////////////////////////// - /// - /// Provide a integer describing the object - /// - /// Integer description of the object - //////////////////////////////////////////////////////////// - public override int GetHashCode() => unchecked((int)((uint)Left ^ - (((uint)Top << 13) | ((uint)Top >> 19)) ^ - (((uint)Width << 26) | ((uint)Width >> 6)) ^ - (((uint)Height << 7) | ((uint)Height >> 25)))); - - //////////////////////////////////////////////////////////// - /// - /// Operator == overload ; check rect equality - /// - /// First rect - /// Second rect - /// r1 == r2 - //////////////////////////////////////////////////////////// - public static bool operator ==(IntRect r1, IntRect r2) => r1.Equals(r2); - - //////////////////////////////////////////////////////////// - /// - /// Operator != overload ; check rect inequality - /// - /// First rect - /// Second rect - /// r1 != r2 - //////////////////////////////////////////////////////////// - public static bool operator !=(IntRect r1, IntRect r2) => !r1.Equals(r2); - - /// - /// Converts a tuple of ints to an IntRect - /// - /// The tuple to convert - public static implicit operator IntRect((int Left, int Top, int Width, int Height) tuple) => new IntRect((tuple.Left, tuple.Top), (tuple.Width, tuple.Height)); - - //////////////////////////////////////////////////////////// - /// - /// Explicit casting to another rectangle type - /// - /// Rectangle being casted - /// Casting result - //////////////////////////////////////////////////////////// - public static explicit operator FloatRect(IntRect r) => new FloatRect( - (r.Left, r.Top), - (r.Width, r.Height)); - - /// Left coordinate of the rectangle - public int Left => Position.X; - - /// Top coordinate of the rectangle - public int Top => Position.Y; - - /// Width of the rectangle - public int Width => Size.X; - - /// Height of the rectangle - public int Height => Size.Y; - - /// Position of the center of the rectangle - public Vector2i Center => Position + (Size / 2); - - /// Position of the top-left corner of the rectangle - public Vector2i Position; - - /// Size of the rectangle - public Vector2i Size; + /// + /// Deconstructs an IntRect into a tuple of ints + /// + /// Left coordinate of the rectangle + /// Top coordinate of the rectangle + /// Width of the rectangle + /// Height of the rectangle + public readonly void Deconstruct(out int left, out int top, out int width, out int height) + { + left = Position.X; + top = Position.Y; + width = Size.X; + height = Size.Y; } //////////////////////////////////////////////////////////// /// - /// FloatRect is an utility class for manipulating 2D rectangles - /// with float coordinates + /// Provide a string describing the object + /// + /// String description of the object + //////////////////////////////////////////////////////////// + public override readonly string ToString() => $"[IntRect] Position({Left}, {Top}) Size({Width}, {Height})"; + + //////////////////////////////////////////////////////////// + /// + /// Compare rectangle and object and checks if they are equal + /// + /// Object to check + /// Object and rectangle are equal + //////////////////////////////////////////////////////////// + public override readonly bool Equals(object obj) => obj is IntRect rect && Equals(rect); + + /////////////////////////////////////////////////////////// + /// + /// Compare two rectangles and checks if they are equal + /// + /// Rectangle to check + /// Rectangles are equal + //////////////////////////////////////////////////////////// + public readonly bool Equals(IntRect other) => Left == other.Left && + Top == other.Top && + Width == other.Width && + Height == other.Height; + + //////////////////////////////////////////////////////////// + /// + /// Provide a integer describing the object + /// + /// Integer description of the object + //////////////////////////////////////////////////////////// + public override readonly int GetHashCode() => unchecked((int)((uint)Left ^ + (((uint)Top << 13) | ((uint)Top >> 19)) ^ + (((uint)Width << 26) | ((uint)Width >> 6)) ^ + (((uint)Height << 7) | ((uint)Height >> 25)))); + + //////////////////////////////////////////////////////////// + /// + /// Operator == overload ; check rect equality + /// + /// First rect + /// Second rect + /// r1 == r2 + //////////////////////////////////////////////////////////// + public static bool operator ==(IntRect r1, IntRect r2) => r1.Equals(r2); + + //////////////////////////////////////////////////////////// + /// + /// Operator != overload ; check rect inequality + /// + /// First rect + /// Second rect + /// r1 != r2 + //////////////////////////////////////////////////////////// + public static bool operator !=(IntRect r1, IntRect r2) => !r1.Equals(r2); + + /// + /// Converts a tuple of ints to an IntRect + /// + /// The tuple to convert + public static implicit operator IntRect((int Left, int Top, int Width, int Height) tuple) => new((tuple.Left, tuple.Top), (tuple.Width, tuple.Height)); + + //////////////////////////////////////////////////////////// + /// + /// Explicit casting to another rectangle type + /// + /// Rectangle being casted + /// Casting result + //////////////////////////////////////////////////////////// + public static explicit operator FloatRect(IntRect r) => new( + (r.Left, r.Top), + (r.Width, r.Height)); + + /// Left coordinate of the rectangle + public readonly int Left => Position.X; + + /// Top coordinate of the rectangle + public readonly int Top => Position.Y; + + /// Width of the rectangle + public readonly int Width => Size.X; + + /// Height of the rectangle + public readonly int Height => Size.Y; + + /// Position of the center of the rectangle + public readonly Vector2i Center => Position + (Size / 2); + + /// Position of the top-left corner of the rectangle + public Vector2i Position; + + /// Size of the rectangle + public Vector2i Size; +} + +//////////////////////////////////////////////////////////// +/// +/// FloatRect is an utility class for manipulating 2D rectangles +/// with float coordinates +/// +//////////////////////////////////////////////////////////// +[StructLayout(LayoutKind.Sequential)] +public struct FloatRect : IEquatable +{ + //////////////////////////////////////////////////////////// + /// + /// Construct the rectangle from position and size /// + /// Position of the top-left corner of the rectangle + /// Size of the rectangle //////////////////////////////////////////////////////////// - [StructLayout(LayoutKind.Sequential)] - public struct FloatRect : IEquatable + public FloatRect(Vector2f position, Vector2f size) { - //////////////////////////////////////////////////////////// - /// - /// Construct the rectangle from position and size - /// - /// Position of the top-left corner of the rectangle - /// Size of the rectangle - //////////////////////////////////////////////////////////// - public FloatRect(Vector2f position, Vector2f size) - { - Position = position; - Size = size; - } + Position = position; + Size = size; + } - //////////////////////////////////////////////////////////// - /// - /// Check if a point is inside the rectangle's area - /// - /// Point to test - /// True if the point is inside - //////////////////////////////////////////////////////////// - public bool Contains(Vector2f point) - { - var minX = Math.Min(Left, Left + Width); - var maxX = Math.Max(Left, Left + Width); - var minY = Math.Min(Top, Top + Height); - var maxY = Math.Max(Top, Top + Height); + //////////////////////////////////////////////////////////// + /// + /// Check if a point is inside the rectangle's area + /// + /// Point to test + /// True if the point is inside + //////////////////////////////////////////////////////////// + public readonly bool Contains(Vector2f point) + { + var minX = Math.Min(Left, Left + Width); + var maxX = Math.Max(Left, Left + Width); + var minY = Math.Min(Top, Top + Height); + var maxY = Math.Max(Top, Top + Height); - return (point.X >= minX) && (point.X < maxX) && (point.Y >= minY) && (point.Y < maxY); - } + return point.X >= minX && point.X < maxX && point.Y >= minY && point.Y < maxY; + } - //////////////////////////////////////////////////////////// - /// - /// Check if a point is inside the rectangle's area - /// - /// Vector2 position of the point to test - /// True if the point is inside - //////////////////////////////////////////////////////////// - public bool Contains(Vector2i point) => Contains((Vector2f)point); - - //////////////////////////////////////////////////////////// - /// - /// Check if a point is inside the rectangle's area - /// - /// Vector2 position of the point to test - /// True if the point is inside - //////////////////////////////////////////////////////////// - public bool Contains(Vector2u point) => Contains((Vector2f)point); - - //////////////////////////////////////////////////////////// - /// - /// Check intersection between two rectangles - /// - /// Rectangle to test - /// True if rectangles overlap - //////////////////////////////////////////////////////////// - public FloatRect? FindIntersection(FloatRect rect) - { - // Rectangles with negative dimensions are allowed, so we must handle them correctly - - // Compute the min and max of the first rectangle on both axes - var r1MinX = Math.Min(Left, Left + Width); - var r1MaxX = Math.Max(Left, Left + Width); - var r1MinY = Math.Min(Top, Top + Height); - var r1MaxY = Math.Max(Top, Top + Height); - - // Compute the min and max of the second rectangle on both axes - var r2MinX = Math.Min(rect.Left, rect.Left + rect.Width); - var r2MaxX = Math.Max(rect.Left, rect.Left + rect.Width); - var r2MinY = Math.Min(rect.Top, rect.Top + rect.Height); - var r2MaxY = Math.Max(rect.Top, rect.Top + rect.Height); - - // Compute the intersection boundaries - var interLeft = Math.Max(r1MinX, r2MinX); - var interTop = Math.Max(r1MinY, r2MinY); - var interRight = Math.Min(r1MaxX, r2MaxX); - var interBottom = Math.Min(r1MaxY, r2MaxY); - - // If the intersection is valid (positive non zero area), then there is an intersection - if ((interLeft < interRight) && (interTop < interBottom)) - { - return new FloatRect((interLeft, interTop), (interRight - interLeft, interBottom - interTop)); - } - else - { - return null; - } - } + //////////////////////////////////////////////////////////// + /// + /// Check if a point is inside the rectangle's area + /// + /// Vector2 position of the point to test + /// True if the point is inside + //////////////////////////////////////////////////////////// + public readonly bool Contains(Vector2i point) => Contains((Vector2f)point); + + //////////////////////////////////////////////////////////// + /// + /// Check if a point is inside the rectangle's area + /// + /// Vector2 position of the point to test + /// True if the point is inside + //////////////////////////////////////////////////////////// + public readonly bool Contains(Vector2u point) => Contains((Vector2f)point); - /// - /// Deconstructs a FloatRect into a tuple of floats - /// - /// Left coordinate of the rectangle - /// Top coordinate of the rectangle - /// Width of the rectangle - /// Height of the rectangle - public void Deconstruct(out float left, out float top, out float width, out float height) + //////////////////////////////////////////////////////////// + /// + /// Check intersection between two rectangles + /// + /// Rectangle to test + /// True if rectangles overlap + //////////////////////////////////////////////////////////// + public readonly FloatRect? FindIntersection(FloatRect rect) + { + // Rectangles with negative dimensions are allowed, so we must handle them correctly + + // Compute the min and max of the first rectangle on both axes + var r1MinX = Math.Min(Left, Left + Width); + var r1MaxX = Math.Max(Left, Left + Width); + var r1MinY = Math.Min(Top, Top + Height); + var r1MaxY = Math.Max(Top, Top + Height); + + // Compute the min and max of the second rectangle on both axes + var r2MinX = Math.Min(rect.Left, rect.Left + rect.Width); + var r2MaxX = Math.Max(rect.Left, rect.Left + rect.Width); + var r2MinY = Math.Min(rect.Top, rect.Top + rect.Height); + var r2MaxY = Math.Max(rect.Top, rect.Top + rect.Height); + + // Compute the intersection boundaries + var interLeft = Math.Max(r1MinX, r2MinX); + var interTop = Math.Max(r1MinY, r2MinY); + var interRight = Math.Min(r1MaxX, r2MaxX); + var interBottom = Math.Min(r1MaxY, r2MaxY); + + // If the intersection is valid (positive non zero area), then there is an intersection + if (interLeft < interRight && interTop < interBottom) { - left = Left; - top = Top; - width = Width; - height = Height; + return new FloatRect((interLeft, interTop), (interRight - interLeft, interBottom - interTop)); } - //////////////////////////////////////////////////////////// - /// - /// Provide a string describing the object - /// - /// String description of the object - //////////////////////////////////////////////////////////// - public override string ToString() => $"[FloatRect] Position({Left}, {Top}) Size({Width}, {Height})"; - - //////////////////////////////////////////////////////////// - /// - /// Compare rectangle and object and checks if they are equal - /// - /// Object to check - /// Object and rectangle are equal - //////////////////////////////////////////////////////////// - public override bool Equals(object obj) => (obj is FloatRect rect) && Equals(rect); - - /////////////////////////////////////////////////////////// - /// - /// Compare two rectangles and checks if they are equal - /// - /// Rectangle to check - /// Rectangles are equal - //////////////////////////////////////////////////////////// - public bool Equals(FloatRect other) => - Position == other.Position && - Size == other.Size; - - //////////////////////////////////////////////////////////// - /// - /// Provide a integer describing the object - /// - /// Integer description of the object - //////////////////////////////////////////////////////////// - public override int GetHashCode() => unchecked((int)((uint)Left ^ - (((uint)Top << 13) | ((uint)Top >> 19)) ^ - (((uint)Width << 26) | ((uint)Width >> 6)) ^ - (((uint)Height << 7) | ((uint)Height >> 25)))); - - //////////////////////////////////////////////////////////// - /// - /// Operator == overload ; check rect equality - /// - /// First rect - /// Second rect - /// r1 == r2 - //////////////////////////////////////////////////////////// - public static bool operator ==(FloatRect r1, FloatRect r2) => r1.Equals(r2); - - //////////////////////////////////////////////////////////// - /// - /// Operator != overload ; check rect inequality - /// - /// First rect - /// Second rect - /// r1 != r2 - //////////////////////////////////////////////////////////// - public static bool operator !=(FloatRect r1, FloatRect r2) => !r1.Equals(r2); - - /// - /// Converts a tuple of floats to a FloatRect - /// - /// The tuple to convert - public static implicit operator FloatRect((float Left, float Top, float Width, float Height) tuple) => new FloatRect((tuple.Left, tuple.Top), (tuple.Width, tuple.Height)); - - //////////////////////////////////////////////////////////// - /// - /// Explicit casting to another rectangle type - /// - /// Rectangle being casted - /// Casting result - //////////////////////////////////////////////////////////// - public static explicit operator IntRect(FloatRect r) => new IntRect( - ((int)r.Left, (int)r.Top), - ((int)r.Width, (int)r.Height)); - - /// Left coordinate of the rectangle - public float Left => Position.X; - - /// Top coordinate of the rectangle - public float Top => Position.Y; - - /// Width of the rectangle - public float Width => Size.X; - - /// Height of the rectangle - public float Height => Size.Y; - - /// Position of the center of the rectangle - public Vector2f Center => Position + (Size / 2f); - - /// Position of the top-left corner of the rectangle - public Vector2f Position; - - /// Size of the rectangle - public Vector2f Size; + return null; } + + /// + /// Deconstructs a FloatRect into a tuple of floats + /// + /// Left coordinate of the rectangle + /// Top coordinate of the rectangle + /// Width of the rectangle + /// Height of the rectangle + public readonly void Deconstruct(out float left, out float top, out float width, out float height) + { + left = Left; + top = Top; + width = Width; + height = Height; + } + + //////////////////////////////////////////////////////////// + /// + /// Provide a string describing the object + /// + /// String description of the object + //////////////////////////////////////////////////////////// + public override readonly string ToString() => $"[FloatRect] Position({Left}, {Top}) Size({Width}, {Height})"; + + //////////////////////////////////////////////////////////// + /// + /// Compare rectangle and object and checks if they are equal + /// + /// Object to check + /// Object and rectangle are equal + //////////////////////////////////////////////////////////// + public override readonly bool Equals(object obj) => obj is FloatRect rect && Equals(rect); + + /////////////////////////////////////////////////////////// + /// + /// Compare two rectangles and checks if they are equal + /// + /// Rectangle to check + /// Rectangles are equal + //////////////////////////////////////////////////////////// + public readonly bool Equals(FloatRect other) => + Position == other.Position && + Size == other.Size; + + //////////////////////////////////////////////////////////// + /// + /// Provide a integer describing the object + /// + /// Integer description of the object + //////////////////////////////////////////////////////////// + public override readonly int GetHashCode() => unchecked((int)((uint)Left ^ + (((uint)Top << 13) | ((uint)Top >> 19)) ^ + (((uint)Width << 26) | ((uint)Width >> 6)) ^ + (((uint)Height << 7) | ((uint)Height >> 25)))); + + //////////////////////////////////////////////////////////// + /// + /// Operator == overload ; check rect equality + /// + /// First rect + /// Second rect + /// r1 == r2 + //////////////////////////////////////////////////////////// + public static bool operator ==(FloatRect r1, FloatRect r2) => r1.Equals(r2); + + //////////////////////////////////////////////////////////// + /// + /// Operator != overload ; check rect inequality + /// + /// First rect + /// Second rect + /// r1 != r2 + //////////////////////////////////////////////////////////// + public static bool operator !=(FloatRect r1, FloatRect r2) => !r1.Equals(r2); + + /// + /// Converts a tuple of floats to a FloatRect + /// + /// The tuple to convert + public static implicit operator FloatRect((float Left, float Top, float Width, float Height) tuple) => new((tuple.Left, tuple.Top), (tuple.Width, tuple.Height)); + + //////////////////////////////////////////////////////////// + /// + /// Explicit casting to another rectangle type + /// + /// Rectangle being casted + /// Casting result + //////////////////////////////////////////////////////////// + public static explicit operator IntRect(FloatRect r) => new( + ((int)r.Left, (int)r.Top), + ((int)r.Width, (int)r.Height)); + + /// Left coordinate of the rectangle + public readonly float Left => Position.X; + + /// Top coordinate of the rectangle + public readonly float Top => Position.Y; + + /// Width of the rectangle + public readonly float Width => Size.X; + + /// Height of the rectangle + public readonly float Height => Size.Y; + + /// Position of the center of the rectangle + public readonly Vector2f Center => Position + (Size / 2f); + + /// Position of the top-left corner of the rectangle + public Vector2f Position; + + /// Size of the rectangle + public Vector2f Size; } diff --git a/src/SFML.Graphics/RectangleShape.cs b/src/SFML.Graphics/RectangleShape.cs index 8f8b30f6..1539877d 100644 --- a/src/SFML.Graphics/RectangleShape.cs +++ b/src/SFML.Graphics/RectangleShape.cs @@ -3,112 +3,104 @@ using System.Security; using SFML.System; -namespace SFML.Graphics +namespace SFML.Graphics; + +//////////////////////////////////////////////////////////// +/// +/// Specialized shape representing a rectangle +/// +//////////////////////////////////////////////////////////// +public class RectangleShape : Shape { //////////////////////////////////////////////////////////// /// - /// Specialized shape representing a rectangle + /// Default constructor /// //////////////////////////////////////////////////////////// - public class RectangleShape : Shape + public RectangleShape() : + this(new Vector2f(0, 0)) { - //////////////////////////////////////////////////////////// - /// - /// Default constructor - /// - //////////////////////////////////////////////////////////// - public RectangleShape() : - this(new Vector2f(0, 0)) - { - } + } - //////////////////////////////////////////////////////////// - /// - /// Construct the shape with an initial size - /// - /// Size of the shape - //////////////////////////////////////////////////////////// - public RectangleShape(Vector2f size) => Size = size; + //////////////////////////////////////////////////////////// + /// + /// Construct the shape with an initial size + /// + /// Size of the shape + //////////////////////////////////////////////////////////// + public RectangleShape(Vector2f size) => Size = size; - //////////////////////////////////////////////////////////// - /// - /// Construct the shape from another shape - /// - /// Shape to copy - //////////////////////////////////////////////////////////// - public RectangleShape(RectangleShape copy) : - base(copy) => Size = copy.Size; + //////////////////////////////////////////////////////////// + /// + /// Construct the shape from another shape + /// + /// Shape to copy + //////////////////////////////////////////////////////////// + public RectangleShape(RectangleShape copy) : + base(copy) => Size = copy.Size; - //////////////////////////////////////////////////////////// - /// - /// The size of the rectangle - /// - //////////////////////////////////////////////////////////// - public Vector2f Size + //////////////////////////////////////////////////////////// + /// + /// The size of the rectangle + /// + //////////////////////////////////////////////////////////// + public Vector2f Size + { + get => _size; + set { - get => _size; - set - { - _size = value; - Update(); - } + _size = value; + Update(); } + } - //////////////////////////////////////////////////////////// - /// - /// Get the total number of points of the rectangle. - /// - /// The total point count. For rectangle shapes, - /// this number is always 4. - //////////////////////////////////////////////////////////// - public override uint GetPointCount() => 4; + //////////////////////////////////////////////////////////// + /// + /// Get the total number of points of the rectangle. + /// + /// The total point count. For rectangle shapes, + /// this number is always 4. + //////////////////////////////////////////////////////////// + public override uint GetPointCount() => 4; - //////////////////////////////////////////////////////////// - /// - /// 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. - /// - /// Index of the point to get, in range [0 .. 3] - /// index-th point of the shape - //////////////////////////////////////////////////////////// - public override Vector2f GetPoint(uint index) + //////////////////////////////////////////////////////////// + /// + /// 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. + /// + /// Index of the point to get, in range [0 .. 3] + /// index-th point of the shape + //////////////////////////////////////////////////////////// + public override Vector2f GetPoint(uint index) => + index switch { - switch (index) - { - default: - case 0: - return new Vector2f(0, 0); - case 1: - return new Vector2f(_size.X, 0); - case 2: - return new Vector2f(_size.X, _size.Y); - case 3: - return new Vector2f(0, _size.Y); - } - } + 1 => new Vector2f(_size.X, 0), + 2 => new Vector2f(_size.X, _size.Y), + 3 => new Vector2f(0, _size.Y), + _ => new Vector2f(0, 0), + }; - //////////////////////////////////////////////////////////// - /// - /// 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. - /// - /// - /// The geometric center of the shape - //////////////////////////////////////////////////////////// - public override Vector2f GetGeometricCenter() => sfRectangleShape_getGeometricCenter(CPointer); + //////////////////////////////////////////////////////////// + /// + /// 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. + /// + /// + /// The geometric center of the shape + //////////////////////////////////////////////////////////// + public override Vector2f GetGeometricCenter() => sfRectangleShape_getGeometricCenter(CPointer); - private Vector2f _size; + private Vector2f _size; - #region Imports - [DllImport(CSFML.Graphics, CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] - private static extern Vector2f sfRectangleShape_getGeometricCenter(IntPtr cPointer); - #endregion - } + #region Imports + [DllImport(CSFML.Graphics, CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] + private static extern Vector2f sfRectangleShape_getGeometricCenter(IntPtr cPointer); + #endregion } diff --git a/src/SFML.Graphics/RenderStates.cs b/src/SFML.Graphics/RenderStates.cs index c7a5a5fd..99e218ee 100644 --- a/src/SFML.Graphics/RenderStates.cs +++ b/src/SFML.Graphics/RenderStates.cs @@ -1,155 +1,154 @@ using System; using System.Runtime.InteropServices; -namespace SFML.Graphics +namespace SFML.Graphics; + +//////////////////////////////////////////////////////////// +/// +/// Define the states used for drawing to a RenderTarget +/// +//////////////////////////////////////////////////////////// +public struct RenderStates { //////////////////////////////////////////////////////////// /// - /// Define the states used for drawing to a RenderTarget + /// Construct a default set of render states with a custom blend mode /// + /// Blend mode to use //////////////////////////////////////////////////////////// - public struct RenderStates + public RenderStates(BlendMode blendMode) : + this(blendMode, StencilMode.Default, Transform.Identity, CoordinateType.Pixels, null, null) { - //////////////////////////////////////////////////////////// - /// - /// Construct a default set of render states with a custom blend mode - /// - /// Blend mode to use - //////////////////////////////////////////////////////////// - public RenderStates(BlendMode blendMode) : - this(blendMode, StencilMode.Default, Transform.Identity, CoordinateType.Pixels, null, null) - { - } - - //////////////////////////////////////////////////////////// - /// - /// Construct a default set of render states with a custom stencil mode - /// - /// Stencil mode to use - //////////////////////////////////////////////////////////// - public RenderStates(StencilMode stencilMode) : - this(BlendMode.Alpha, stencilMode, Transform.Identity, CoordinateType.Pixels, null, null) - { - } - - //////////////////////////////////////////////////////////// - /// - /// Construct a default set of render states with a custom transform - /// - /// Transform to use - //////////////////////////////////////////////////////////// - public RenderStates(Transform transform) : - this(BlendMode.Alpha, StencilMode.Default, transform, CoordinateType.Pixels, null, null) - { - } - - //////////////////////////////////////////////////////////// - /// - /// Construct a default set of render states with a custom texture - /// - /// Texture to use - //////////////////////////////////////////////////////////// - public RenderStates(Texture texture) : - this(BlendMode.Alpha, StencilMode.Default, Transform.Identity, CoordinateType.Pixels, texture, null) - { - } - - //////////////////////////////////////////////////////////// - /// - /// Construct a default set of render states with a custom shader - /// - /// Shader to use - //////////////////////////////////////////////////////////// - public RenderStates(Shader shader) : - this(BlendMode.Alpha, StencilMode.Default, Transform.Identity, CoordinateType.Pixels, null, shader) - { - } - - //////////////////////////////////////////////////////////// - /// - /// Construct a set of render states with all its attributes - /// - /// Blend mode to use - /// Stencil mode to use - /// Transform to use - /// Coordinate type to use - /// Texture to use - /// Shader to use - //////////////////////////////////////////////////////////// - public RenderStates(BlendMode blendMode, StencilMode stencilMode, Transform transform, CoordinateType coordinateType, Texture texture, Shader shader) - { - BlendMode = blendMode; - StencilMode = stencilMode; - Transform = transform; - CoordinateType = coordinateType; - Texture = texture; - Shader = shader; - } - - //////////////////////////////////////////////////////////// - /// - /// Copy constructor - /// - /// States to copy - //////////////////////////////////////////////////////////// - public RenderStates(RenderStates copy) - { - BlendMode = copy.BlendMode; - StencilMode = copy.StencilMode; - Transform = copy.Transform; - CoordinateType = copy.CoordinateType; - Texture = copy.Texture; - Shader = copy.Shader; - } - - //////////////////////////////////////////////////////////// - /// Special instance holding the default render states - //////////////////////////////////////////////////////////// - public static RenderStates Default => new RenderStates(BlendMode.Alpha, StencilMode.Default, Transform.Identity, CoordinateType.Pixels, null, null); - - /// Blending mode - public BlendMode BlendMode; + } - /// Stencil mode - public StencilMode StencilMode; + //////////////////////////////////////////////////////////// + /// + /// Construct a default set of render states with a custom stencil mode + /// + /// Stencil mode to use + //////////////////////////////////////////////////////////// + public RenderStates(StencilMode stencilMode) : + this(BlendMode.Alpha, stencilMode, Transform.Identity, CoordinateType.Pixels, null, null) + { + } - /// Transform - public Transform Transform; + //////////////////////////////////////////////////////////// + /// + /// Construct a default set of render states with a custom transform + /// + /// Transform to use + //////////////////////////////////////////////////////////// + public RenderStates(Transform transform) : + this(BlendMode.Alpha, StencilMode.Default, transform, CoordinateType.Pixels, null, null) + { + } - /// Texture coordinate type - public CoordinateType CoordinateType; + //////////////////////////////////////////////////////////// + /// + /// Construct a default set of render states with a custom texture + /// + /// Texture to use + //////////////////////////////////////////////////////////// + public RenderStates(Texture texture) : + this(BlendMode.Alpha, StencilMode.Default, Transform.Identity, CoordinateType.Pixels, texture, null) + { + } - /// Texture - public Texture Texture; + //////////////////////////////////////////////////////////// + /// + /// Construct a default set of render states with a custom shader + /// + /// Shader to use + //////////////////////////////////////////////////////////// + public RenderStates(Shader shader) : + this(BlendMode.Alpha, StencilMode.Default, Transform.Identity, CoordinateType.Pixels, null, shader) + { + } - /// Shader - public Shader Shader; + //////////////////////////////////////////////////////////// + /// + /// Construct a set of render states with all its attributes + /// + /// Blend mode to use + /// Stencil mode to use + /// Transform to use + /// Coordinate type to use + /// Texture to use + /// Shader to use + //////////////////////////////////////////////////////////// + public RenderStates(BlendMode blendMode, StencilMode stencilMode, Transform transform, CoordinateType coordinateType, Texture texture, Shader shader) + { + BlendMode = blendMode; + StencilMode = stencilMode; + Transform = transform; + CoordinateType = coordinateType; + Texture = texture; + Shader = shader; + } - // Return a marshalled version of the instance, that can directly be passed to the C API - internal MarshalData Marshal() - { - var data = new MarshalData - { - BlendMode = BlendMode, - StencilMode = StencilMode, - Transform = Transform, - CoordinateType = CoordinateType, - Texture = Texture != null ? Texture.CPointer : IntPtr.Zero, - Shader = Shader != null ? Shader.CPointer : IntPtr.Zero - }; - - return data; - } - - [StructLayout(LayoutKind.Sequential)] - internal struct MarshalData + //////////////////////////////////////////////////////////// + /// + /// Copy constructor + /// + /// States to copy + //////////////////////////////////////////////////////////// + public RenderStates(RenderStates copy) + { + BlendMode = copy.BlendMode; + StencilMode = copy.StencilMode; + Transform = copy.Transform; + CoordinateType = copy.CoordinateType; + Texture = copy.Texture; + Shader = copy.Shader; + } + + //////////////////////////////////////////////////////////// + /// Special instance holding the default render states + //////////////////////////////////////////////////////////// + public static RenderStates Default => new(BlendMode.Alpha, StencilMode.Default, Transform.Identity, CoordinateType.Pixels, null, null); + + /// Blending mode + public BlendMode BlendMode; + + /// Stencil mode + public StencilMode StencilMode; + + /// Transform + public Transform Transform; + + /// Texture coordinate type + public CoordinateType CoordinateType; + + /// Texture + public Texture Texture; + + /// Shader + public Shader Shader; + + // Return a marshalled version of the instance, that can directly be passed to the C API + internal MarshalData Marshal() + { + var data = new MarshalData { - public BlendMode BlendMode; - public StencilMode StencilMode; - public Transform Transform; - public CoordinateType CoordinateType; - public IntPtr Texture; - public IntPtr Shader; - } + BlendMode = BlendMode, + StencilMode = StencilMode, + Transform = Transform, + CoordinateType = CoordinateType, + Texture = Texture?.CPointer ?? IntPtr.Zero, + Shader = Shader?.CPointer ?? IntPtr.Zero + }; + + return data; + } + + [StructLayout(LayoutKind.Sequential)] + internal struct MarshalData + { + public BlendMode BlendMode; + public StencilMode StencilMode; + public Transform Transform; + public CoordinateType CoordinateType; + public IntPtr Texture; + public IntPtr Shader; } } diff --git a/src/SFML.Graphics/RenderTexture.cs b/src/SFML.Graphics/RenderTexture.cs index 15e814b0..bfc3b4e3 100644 --- a/src/SFML.Graphics/RenderTexture.cs +++ b/src/SFML.Graphics/RenderTexture.cs @@ -4,570 +4,569 @@ using SFML.System; using SFML.Window; -namespace SFML.Graphics +namespace SFML.Graphics; + +//////////////////////////////////////////////////////////// +/// +/// Target for off-screen 2D rendering into an texture +/// +//////////////////////////////////////////////////////////// +public class RenderTexture : ObjectBase, IRenderTarget { //////////////////////////////////////////////////////////// /// - /// Target for off-screen 2D rendering into an texture + /// Create the render-texture with the given dimensions /// + /// Width and height of the render-texture //////////////////////////////////////////////////////////// - public class RenderTexture : ObjectBase, IRenderTarget + public RenderTexture(Vector2u size) : + this(size, default) { - //////////////////////////////////////////////////////////// - /// - /// Create the render-texture with the given dimensions - /// - /// Width and height of the render-texture - //////////////////////////////////////////////////////////// - public RenderTexture(Vector2u size) : - this(size, default) - { - } + } - //////////////////////////////////////////////////////////// - /// - /// Create the render-texture with the given dimensions and - /// a ContextSettings. - /// - /// Width and height of the render-texture - /// A ContextSettings struct representing settings for the RenderTexture - //////////////////////////////////////////////////////////// - public RenderTexture(Vector2u size, ContextSettings contextSettings) : - base(sfRenderTexture_create(size, ref contextSettings)) - { - _defaultView = new View(sfRenderTexture_getDefaultView(CPointer)); - Texture = new Texture(sfRenderTexture_getTexture(CPointer)); - GC.SuppressFinalize(_defaultView); - GC.SuppressFinalize(Texture); - } + //////////////////////////////////////////////////////////// + /// + /// Create the render-texture with the given dimensions and + /// a ContextSettings. + /// + /// Width and height of the render-texture + /// A ContextSettings struct representing settings for the RenderTexture + //////////////////////////////////////////////////////////// + public RenderTexture(Vector2u size, ContextSettings contextSettings) : + base(sfRenderTexture_create(size, ref contextSettings)) + { + _defaultView = new View(sfRenderTexture_getDefaultView(CPointer)); + Texture = new Texture(sfRenderTexture_getTexture(CPointer)); + GC.SuppressFinalize(_defaultView); + GC.SuppressFinalize(Texture); + } - //////////////////////////////////////////////////////////// - /// - /// Activate of deactivate the render texture as the current target - /// for rendering - /// - /// True to activate, false to deactivate (true by default) - /// True if operation was successful, false otherwise - //////////////////////////////////////////////////////////// - public bool SetActive(bool active) => sfRenderTexture_setActive(CPointer, active); - - //////////////////////////////////////////////////////////// - /// - /// Enable or disable texture repeating - /// - /// - /// - /// This property is similar to . - /// This parameter is disabled by default. - /// - //////////////////////////////////////////////////////////// - public bool Repeated - { - get => sfRenderTexture_isRepeated(CPointer); - set => sfRenderTexture_setRepeated(CPointer, value); - } + //////////////////////////////////////////////////////////// + /// + /// Activate of deactivate the render texture as the current target + /// for rendering + /// + /// True to activate, false to deactivate (true by default) + /// True if operation was successful, false otherwise + //////////////////////////////////////////////////////////// + public bool SetActive(bool active) => sfRenderTexture_setActive(CPointer, active); - //////////////////////////////////////////////////////////// - /// - /// Size of the rendering region of the render texture - /// - //////////////////////////////////////////////////////////// - public Vector2u Size => sfRenderTexture_getSize(CPointer); - - //////////////////////////////////////////////////////////// - /// - /// Tell if the render texture will use sRGB encoding when drawing on it - /// - //////////////////////////////////////////////////////////// - public bool IsSrgb => sfRenderTexture_isSrgb(CPointer); - - //////////////////////////////////////////////////////////// - /// - /// Default view of the render texture - /// - //////////////////////////////////////////////////////////// - public View DefaultView => new View(_defaultView); - - //////////////////////////////////////////////////////////// - /// - /// Return the current active view - /// - /// The current view - //////////////////////////////////////////////////////////// - public View GetView() => new View(sfRenderTexture_getView(CPointer)); - - //////////////////////////////////////////////////////////// - /// - /// Change the current active view - /// - /// New view - //////////////////////////////////////////////////////////// - public void SetView(View view) => sfRenderTexture_setView(CPointer, view.CPointer); - - //////////////////////////////////////////////////////////// - /// - /// Get the viewport of a view applied to this target - /// - /// Target view - /// Viewport rectangle, expressed in pixels in the current target - //////////////////////////////////////////////////////////// - public IntRect GetViewport(View view) => sfRenderTexture_getViewport(CPointer, view.CPointer); - - //////////////////////////////////////////////////////////// - /// - /// 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. - /// - /// The view for which we want to compute the scissor rectangle - /// Scissor rectangle, expressed in pixels - //////////////////////////////////////////////////////////// - public IntRect GetScissor(View view) => sfRenderTexture_getScissor(CPointer, view.CPointer); - - //////////////////////////////////////////////////////////// - /// - /// 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: - /// target.MapPixelToCoords(point, target.GetView()); - /// - /// Pixel to convert - /// The converted point, in "world" coordinates - //////////////////////////////////////////////////////////// - public Vector2f MapPixelToCoords(Vector2i point) => MapPixelToCoords(point, GetView()); - - //////////////////////////////////////////////////////////// - /// - /// 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, ie. 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. - /// - /// Pixel to convert - /// The view to use for converting the point - /// The converted point, in "world" coordinates - //////////////////////////////////////////////////////////// - public Vector2f MapPixelToCoords(Vector2i point, View view) => sfRenderTexture_mapPixelToCoords(CPointer, point, view != null ? view.CPointer : IntPtr.Zero); - - //////////////////////////////////////////////////////////// - /// - /// 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: - /// target.MapCoordsToPixel(point, target.GetView()); - /// - /// Point to convert - /// The converted point, in target coordinates (pixels) - //////////////////////////////////////////////////////////// - public Vector2i MapCoordsToPixel(Vector2f point) => MapCoordsToPixel(point, GetView()); - - //////////////////////////////////////////////////////////// - /// - /// 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, ie. 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. - /// - /// Point to convert - /// The view to use for converting the point - /// The converted point, in target coordinates (pixels) - //////////////////////////////////////////////////////////// - public Vector2i MapCoordsToPixel(Vector2f point, View view) => sfRenderTexture_mapCoordsToPixel(CPointer, point, view != null ? view.CPointer : IntPtr.Zero); - - //////////////////////////////////////////////////////////// - /// - /// Generate a mipmap using the current texture data - /// - /// - /// - /// This function is similar to 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. - /// - /// - /// True if mipmap generation was successful, false if unsuccessful - //////////////////////////////////////////////////////////// - public bool GenerateMipmap() => sfRenderTexture_generateMipmap(CPointer); - - //////////////////////////////////////////////////////////// - /// - /// Clear the entire render texture with black color - /// - //////////////////////////////////////////////////////////// - public void Clear() => sfRenderTexture_clear(CPointer, Color.Black); - - //////////////////////////////////////////////////////////// - /// - /// Clear the entire render texture with a single color - /// - /// Color to use to clear the texture - //////////////////////////////////////////////////////////// - public void Clear(Color color) => sfRenderTexture_clear(CPointer, color); - - //////////////////////////////////////////////////////////// - /// - /// 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. - /// - /// Fill color to use to clear the render target - /// Stencil value to clear to - //////////////////////////////////////////////////////////// - public void Clear(Color color, StencilValue stencilValue) => sfRenderTexture_clearColorAndStencil(CPointer, color, stencilValue); - - //////////////////////////////////////////////////////////// - /// - /// Clear the stencil buffer to a specific value - /// - /// The specified value is truncated to the bit width of - /// the current stencil buffer. - /// - /// Stencil value to clear to - //////////////////////////////////////////////////////////// - public void ClearStencil(StencilValue stencilValue) => sfRenderTexture_clearStencil(CPointer, stencilValue); - - //////////////////////////////////////////////////////////// - /// - /// Update the contents of the target texture - /// - //////////////////////////////////////////////////////////// - public void Display() => sfRenderTexture_display(CPointer); - - //////////////////////////////////////////////////////////// - /// - /// Target texture of the render texture - /// - //////////////////////////////////////////////////////////// - public Texture Texture { get; } - - //////////////////////////////////////////////////////////// - /// - /// The maximum anti-aliasing level supported by the system - /// - //////////////////////////////////////////////////////////// - public static uint MaximumAntiAliasingLevel => sfRenderTexture_getMaximumAntiAliasingLevel(); - - //////////////////////////////////////////////////////////// - /// - /// Control the smooth filter - /// - //////////////////////////////////////////////////////////// - public bool Smooth - { - get => sfRenderTexture_isSmooth(CPointer); - set => sfRenderTexture_setSmooth(CPointer, value); - } + //////////////////////////////////////////////////////////// + /// + /// Enable or disable texture repeating + /// + /// + /// + /// This property is similar to . + /// This parameter is disabled by default. + /// + //////////////////////////////////////////////////////////// + public bool Repeated + { + get => sfRenderTexture_isRepeated(CPointer); + set => sfRenderTexture_setRepeated(CPointer, value); + } - //////////////////////////////////////////////////////////// - /// - /// Draw a drawable object to the render-target, with default render states - /// - /// Object to draw - //////////////////////////////////////////////////////////// - public void Draw(IDrawable drawable) => Draw(drawable, RenderStates.Default); - - //////////////////////////////////////////////////////////// - /// - /// Draw a drawable object to the render-target - /// - /// Object to draw - /// Render states to use for drawing - //////////////////////////////////////////////////////////// - public void Draw(IDrawable drawable, RenderStates states) => drawable.Draw(this, states); - - //////////////////////////////////////////////////////////// - /// - /// Draw primitives defined by an array of vertices, with default render states - /// - /// Pointer to the vertices - /// Type of primitives to draw - //////////////////////////////////////////////////////////// - public void Draw(Vertex[] vertices, PrimitiveType type) => Draw(vertices, type, RenderStates.Default); - - //////////////////////////////////////////////////////////// - /// - /// Draw primitives defined by an array of vertices - /// - /// Pointer to the vertices - /// Type of primitives to draw - /// Render states to use for drawing - //////////////////////////////////////////////////////////// - public void Draw(Vertex[] vertices, PrimitiveType type, RenderStates states) => Draw(vertices, 0, (uint)vertices.Length, type, states); - - //////////////////////////////////////////////////////////// - /// - /// Draw primitives defined by a sub-array of vertices, with default render states - /// - /// Array of vertices to draw - /// Index of the first vertex to draw in the array - /// Number of vertices to draw - /// Type of primitives to draw - //////////////////////////////////////////////////////////// - public void Draw(Vertex[] vertices, uint start, uint count, PrimitiveType type) => Draw(vertices, start, count, type, RenderStates.Default); - - //////////////////////////////////////////////////////////// - /// - /// Draw primitives defined by a sub-array of vertices - /// - /// Pointer to the vertices - /// Index of the first vertex to use in the array - /// Number of vertices to draw - /// Type of primitives to draw - /// Render states to use for drawing - //////////////////////////////////////////////////////////// - public void Draw(Vertex[] vertices, uint start, uint count, PrimitiveType type, RenderStates states) - { - var marshaledStates = states.Marshal(); + //////////////////////////////////////////////////////////// + /// + /// Size of the rendering region of the render texture + /// + //////////////////////////////////////////////////////////// + public Vector2u Size => sfRenderTexture_getSize(CPointer); - unsafe - { - fixed (Vertex* vertexPtr = vertices) - { - sfRenderTexture_drawPrimitives(CPointer, vertexPtr + start, (UIntPtr)count, type, ref marshaledStates); - } - } - } + //////////////////////////////////////////////////////////// + /// + /// Tell if the render texture will use sRGB encoding when drawing on it + /// + //////////////////////////////////////////////////////////// + public bool IsSrgb => sfRenderTexture_isSrgb(CPointer); + + //////////////////////////////////////////////////////////// + /// + /// Default view of the render texture + /// + //////////////////////////////////////////////////////////// + public View DefaultView => new(_defaultView); + + //////////////////////////////////////////////////////////// + /// + /// Return the current active view + /// + /// The current view + //////////////////////////////////////////////////////////// + public View GetView() => new(sfRenderTexture_getView(CPointer)); + + //////////////////////////////////////////////////////////// + /// + /// Change the current active view + /// + /// New view + //////////////////////////////////////////////////////////// + public void SetView(View view) => sfRenderTexture_setView(CPointer, view.CPointer); + + //////////////////////////////////////////////////////////// + /// + /// Get the viewport of a view applied to this target + /// + /// Target view + /// Viewport rectangle, expressed in pixels in the current target + //////////////////////////////////////////////////////////// + public IntRect GetViewport(View view) => sfRenderTexture_getViewport(CPointer, view.CPointer); + + //////////////////////////////////////////////////////////// + /// + /// 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. + /// + /// The view for which we want to compute the scissor rectangle + /// Scissor rectangle, expressed in pixels + //////////////////////////////////////////////////////////// + public IntRect GetScissor(View view) => sfRenderTexture_getScissor(CPointer, view.CPointer); + + //////////////////////////////////////////////////////////// + /// + /// 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: + /// target.MapPixelToCoords(point, target.GetView()); + /// + /// Pixel to convert + /// The converted point, in "world" coordinates + //////////////////////////////////////////////////////////// + public Vector2f MapPixelToCoords(Vector2i point) => MapPixelToCoords(point, GetView()); + + //////////////////////////////////////////////////////////// + /// + /// 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, ie. 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. + /// + /// Pixel to convert + /// The view to use for converting the point + /// The converted point, in "world" coordinates + //////////////////////////////////////////////////////////// + public Vector2f MapPixelToCoords(Vector2i point, View view) => sfRenderTexture_mapPixelToCoords(CPointer, point, view?.CPointer ?? IntPtr.Zero); + + //////////////////////////////////////////////////////////// + /// + /// 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: + /// target.MapCoordsToPixel(point, target.GetView()); + /// + /// Point to convert + /// The converted point, in target coordinates (pixels) + //////////////////////////////////////////////////////////// + public Vector2i MapCoordsToPixel(Vector2f point) => MapCoordsToPixel(point, GetView()); + + //////////////////////////////////////////////////////////// + /// + /// 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, ie. 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. + /// + /// Point to convert + /// The view to use for converting the point + /// The converted point, in target coordinates (pixels) + //////////////////////////////////////////////////////////// + public Vector2i MapCoordsToPixel(Vector2f point, View view) => sfRenderTexture_mapCoordsToPixel(CPointer, point, view?.CPointer ?? IntPtr.Zero); + + //////////////////////////////////////////////////////////// + /// + /// Generate a mipmap using the current texture data + /// + /// + /// + /// This function is similar to 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. + /// + /// + /// True if mipmap generation was successful, false if unsuccessful + //////////////////////////////////////////////////////////// + public bool GenerateMipmap() => sfRenderTexture_generateMipmap(CPointer); + + //////////////////////////////////////////////////////////// + /// + /// Clear the entire render texture with black color + /// + //////////////////////////////////////////////////////////// + public void Clear() => sfRenderTexture_clear(CPointer, Color.Black); + + //////////////////////////////////////////////////////////// + /// + /// Clear the entire render texture with a single color + /// + /// Color to use to clear the texture + //////////////////////////////////////////////////////////// + public void Clear(Color color) => sfRenderTexture_clear(CPointer, color); + + //////////////////////////////////////////////////////////// + /// + /// 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. + /// + /// Fill color to use to clear the render target + /// Stencil value to clear to + //////////////////////////////////////////////////////////// + public void Clear(Color color, StencilValue stencilValue) => sfRenderTexture_clearColorAndStencil(CPointer, color, stencilValue); + + //////////////////////////////////////////////////////////// + /// + /// Clear the stencil buffer to a specific value + /// + /// The specified value is truncated to the bit width of + /// the current stencil buffer. + /// + /// Stencil value to clear to + //////////////////////////////////////////////////////////// + public void ClearStencil(StencilValue stencilValue) => sfRenderTexture_clearStencil(CPointer, stencilValue); + + //////////////////////////////////////////////////////////// + /// + /// Update the contents of the target texture + /// + //////////////////////////////////////////////////////////// + public void Display() => sfRenderTexture_display(CPointer); + + //////////////////////////////////////////////////////////// + /// + /// Target texture of the render texture + /// + //////////////////////////////////////////////////////////// + public Texture Texture { get; } - //////////////////////////////////////////////////////////// - /// - /// 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: - /// - /// // OpenGL code here... - /// window.PushGLStates(); - /// window.Draw(...); - /// window.Draw(...); - /// window.PopGLStates(); - /// // OpenGL code here... - /// - /// 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. - /// - //////////////////////////////////////////////////////////// - public void PushGLStates() => sfRenderTexture_pushGLStates(CPointer); - - //////////////////////////////////////////////////////////// - /// - /// Restore the previously saved OpenGL render states and matrices. - /// - /// See the description of PushGLStates to get a detailed - /// description of these functions. - /// - //////////////////////////////////////////////////////////// - public void PopGLStates() => sfRenderTexture_popGLStates(CPointer); - - //////////////////////////////////////////////////////////// - /// - /// 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: - /// - /// // OpenGL code here... - /// glPushAttrib(...); - /// window.ResetGLStates(); - /// window.Draw(...); - /// window.Draw(...); - /// glPopAttrib(...); - /// // OpenGL code here... - /// - //////////////////////////////////////////////////////////// - public void ResetGLStates() => sfRenderTexture_resetGLStates(CPointer); - - //////////////////////////////////////////////////////////// - /// - /// Provide a string describing the object - /// - /// String description of the object - //////////////////////////////////////////////////////////// - public override string ToString() + //////////////////////////////////////////////////////////// + /// + /// The maximum anti-aliasing level supported by the system + /// + //////////////////////////////////////////////////////////// + public static uint MaximumAntiAliasingLevel => sfRenderTexture_getMaximumAntiAliasingLevel(); + + //////////////////////////////////////////////////////////// + /// + /// Control the smooth filter + /// + //////////////////////////////////////////////////////////// + public bool Smooth + { + get => sfRenderTexture_isSmooth(CPointer); + set => sfRenderTexture_setSmooth(CPointer, value); + } + + //////////////////////////////////////////////////////////// + /// + /// Draw a drawable object to the render-target, with default render states + /// + /// Object to draw + //////////////////////////////////////////////////////////// + public void Draw(IDrawable drawable) => Draw(drawable, RenderStates.Default); + + //////////////////////////////////////////////////////////// + /// + /// Draw a drawable object to the render-target + /// + /// Object to draw + /// Render states to use for drawing + //////////////////////////////////////////////////////////// + public void Draw(IDrawable drawable, RenderStates states) => drawable.Draw(this, states); + + //////////////////////////////////////////////////////////// + /// + /// Draw primitives defined by an array of vertices, with default render states + /// + /// Pointer to the vertices + /// Type of primitives to draw + //////////////////////////////////////////////////////////// + public void Draw(Vertex[] vertices, PrimitiveType type) => Draw(vertices, type, RenderStates.Default); + + //////////////////////////////////////////////////////////// + /// + /// Draw primitives defined by an array of vertices + /// + /// Pointer to the vertices + /// Type of primitives to draw + /// Render states to use for drawing + //////////////////////////////////////////////////////////// + public void Draw(Vertex[] vertices, PrimitiveType type, RenderStates states) => Draw(vertices, 0, (uint)vertices.Length, type, states); + + //////////////////////////////////////////////////////////// + /// + /// Draw primitives defined by a sub-array of vertices, with default render states + /// + /// Array of vertices to draw + /// Index of the first vertex to draw in the array + /// Number of vertices to draw + /// Type of primitives to draw + //////////////////////////////////////////////////////////// + public void Draw(Vertex[] vertices, uint start, uint count, PrimitiveType type) => Draw(vertices, start, count, type, RenderStates.Default); + + //////////////////////////////////////////////////////////// + /// + /// Draw primitives defined by a sub-array of vertices + /// + /// Pointer to the vertices + /// Index of the first vertex to use in the array + /// Number of vertices to draw + /// Type of primitives to draw + /// Render states to use for drawing + //////////////////////////////////////////////////////////// + public void Draw(Vertex[] vertices, uint start, uint count, PrimitiveType type, RenderStates states) + { + var marshaledStates = states.Marshal(); + + unsafe { - if (IsInvalid) + fixed (Vertex* vertexPtr = vertices) { - return MakeDisposedObjectString(); + sfRenderTexture_drawPrimitives(CPointer, vertexPtr + start, (UIntPtr)count, type, ref marshaledStates); } + } + } + + //////////////////////////////////////////////////////////// + /// + /// 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: + /// + /// // OpenGL code here... + /// window.PushGLStates(); + /// window.Draw(...); + /// window.Draw(...); + /// window.PopGLStates(); + /// // OpenGL code here... + /// + /// 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. + /// + //////////////////////////////////////////////////////////// + public void PushGLStates() => sfRenderTexture_pushGLStates(CPointer); + + //////////////////////////////////////////////////////////// + /// + /// Restore the previously saved OpenGL render states and matrices. + /// + /// See the description of PushGLStates to get a detailed + /// description of these functions. + /// + //////////////////////////////////////////////////////////// + public void PopGLStates() => sfRenderTexture_popGLStates(CPointer); + + //////////////////////////////////////////////////////////// + /// + /// 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: + /// + /// // OpenGL code here... + /// glPushAttrib(...); + /// window.ResetGLStates(); + /// window.Draw(...); + /// window.Draw(...); + /// glPopAttrib(...); + /// // OpenGL code here... + /// + //////////////////////////////////////////////////////////// + public void ResetGLStates() => sfRenderTexture_resetGLStates(CPointer); - return "[RenderTexture]" + - " Size(" + Size + ")" + - " Texture(" + Texture + ")" + - " DefaultView(" + DefaultView + ")" + - " View(" + GetView() + ")"; + //////////////////////////////////////////////////////////// + /// + /// Provide a string describing the object + /// + /// String description of the object + //////////////////////////////////////////////////////////// + public override string ToString() + { + if (IsInvalid) + { + return MakeDisposedObjectString(); } - //////////////////////////////////////////////////////////// - /// - /// Handle the destruction of the object - /// - /// Is the GC disposing the object, or is it an explicit call ? - //////////////////////////////////////////////////////////// - protected override void Destroy(bool disposing) + return "[RenderTexture]" + + " Size(" + Size + ")" + + " Texture(" + Texture + ")" + + " DefaultView(" + DefaultView + ")" + + " View(" + GetView() + ")"; + } + + //////////////////////////////////////////////////////////// + /// + /// Handle the destruction of the object + /// + /// Is the GC disposing the object, or is it an explicit call ? + //////////////////////////////////////////////////////////// + protected override void Destroy(bool disposing) + { + if (!disposing) { - if (!disposing) - { - _ = Context.Global.SetActive(true); - } + _ = Context.Global.SetActive(true); + } - sfRenderTexture_destroy(CPointer); + sfRenderTexture_destroy(CPointer); - if (disposing) - { - _defaultView.Dispose(); - Texture.Dispose(); - } + if (disposing) + { + _defaultView.Dispose(); + Texture.Dispose(); + } - if (!disposing) - { - _ = Context.Global.SetActive(false); - } + if (!disposing) + { + _ = Context.Global.SetActive(false); } + } - private readonly View _defaultView; + private readonly View _defaultView; - #region Imports - [DllImport(CSFML.Graphics, CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] - private static extern IntPtr sfRenderTexture_create(Vector2u size, ref ContextSettings settings); + #region Imports + [DllImport(CSFML.Graphics, CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] + private static extern IntPtr sfRenderTexture_create(Vector2u size, ref ContextSettings settings); - [DllImport(CSFML.Graphics, CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] - private static extern void sfRenderTexture_destroy(IntPtr cPointer); + [DllImport(CSFML.Graphics, CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] + private static extern void sfRenderTexture_destroy(IntPtr cPointer); - [DllImport(CSFML.Graphics, CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] - private static extern void sfRenderTexture_clear(IntPtr cPointer, Color clearColor); + [DllImport(CSFML.Graphics, CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] + private static extern void sfRenderTexture_clear(IntPtr cPointer, Color clearColor); - [DllImport(CSFML.Graphics, CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] - private static extern void sfRenderTexture_clearStencil(IntPtr cPointer, StencilValue stencilValue); + [DllImport(CSFML.Graphics, CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] + private static extern void sfRenderTexture_clearStencil(IntPtr cPointer, StencilValue stencilValue); - [DllImport(CSFML.Graphics, CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] - private static extern void sfRenderTexture_clearColorAndStencil(IntPtr cPointer, Color clearColor, StencilValue stencilValue); + [DllImport(CSFML.Graphics, CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] + private static extern void sfRenderTexture_clearColorAndStencil(IntPtr cPointer, Color clearColor, StencilValue stencilValue); - [DllImport(CSFML.Graphics, CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] - private static extern Vector2u sfRenderTexture_getSize(IntPtr cPointer); + [DllImport(CSFML.Graphics, CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] + private static extern Vector2u sfRenderTexture_getSize(IntPtr cPointer); - [DllImport(CSFML.Graphics, CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] - [return: MarshalAs(UnmanagedType.I1)] - private static extern bool sfRenderTexture_isSrgb(IntPtr cPointer); + [DllImport(CSFML.Graphics, CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] + [return: MarshalAs(UnmanagedType.I1)] + private static extern bool sfRenderTexture_isSrgb(IntPtr cPointer); - [DllImport(CSFML.Graphics, CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] - [return: MarshalAs(UnmanagedType.I1)] - private static extern bool sfRenderTexture_setActive(IntPtr cPointer, bool active); + [DllImport(CSFML.Graphics, CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] + [return: MarshalAs(UnmanagedType.I1)] + private static extern bool sfRenderTexture_setActive(IntPtr cPointer, bool active); - [DllImport(CSFML.Graphics, CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] - private static extern void sfRenderTexture_display(IntPtr cPointer); + [DllImport(CSFML.Graphics, CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] + private static extern void sfRenderTexture_display(IntPtr cPointer); - [DllImport(CSFML.Graphics, CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] - private static extern void sfRenderTexture_setView(IntPtr cPointer, IntPtr view); + [DllImport(CSFML.Graphics, CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] + private static extern void sfRenderTexture_setView(IntPtr cPointer, IntPtr view); - [DllImport(CSFML.Graphics, CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] - private static extern IntPtr sfRenderTexture_getView(IntPtr cPointer); + [DllImport(CSFML.Graphics, CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] + private static extern IntPtr sfRenderTexture_getView(IntPtr cPointer); - [DllImport(CSFML.Graphics, CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] - private static extern IntPtr sfRenderTexture_getDefaultView(IntPtr cPointer); + [DllImport(CSFML.Graphics, CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] + private static extern IntPtr sfRenderTexture_getDefaultView(IntPtr cPointer); - [DllImport(CSFML.Graphics, CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] - private static extern IntRect sfRenderTexture_getViewport(IntPtr cPointer, IntPtr targetView); + [DllImport(CSFML.Graphics, CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] + private static extern IntRect sfRenderTexture_getViewport(IntPtr cPointer, IntPtr targetView); - [DllImport(CSFML.Graphics, CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] - private static extern IntRect sfRenderTexture_getScissor(IntPtr cPointer, IntPtr targetView); + [DllImport(CSFML.Graphics, CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] + private static extern IntRect sfRenderTexture_getScissor(IntPtr cPointer, IntPtr targetView); - [DllImport(CSFML.Graphics, CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] - private static extern Vector2i sfRenderTexture_mapCoordsToPixel(IntPtr cPointer, Vector2f point, IntPtr view); + [DllImport(CSFML.Graphics, CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] + private static extern Vector2i sfRenderTexture_mapCoordsToPixel(IntPtr cPointer, Vector2f point, IntPtr view); - [DllImport(CSFML.Graphics, CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] - private static extern Vector2f sfRenderTexture_mapPixelToCoords(IntPtr cPointer, Vector2i point, IntPtr view); + [DllImport(CSFML.Graphics, CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] + private static extern Vector2f sfRenderTexture_mapPixelToCoords(IntPtr cPointer, Vector2i point, IntPtr view); - [DllImport(CSFML.Graphics, CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] - private static extern IntPtr sfRenderTexture_getTexture(IntPtr cPointer); + [DllImport(CSFML.Graphics, CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] + private static extern IntPtr sfRenderTexture_getTexture(IntPtr cPointer); - [DllImport(CSFML.Graphics, CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] - private static extern uint sfRenderTexture_getMaximumAntiAliasingLevel(); + [DllImport(CSFML.Graphics, CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] + private static extern uint sfRenderTexture_getMaximumAntiAliasingLevel(); - [DllImport(CSFML.Graphics, CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] - private static extern void sfRenderTexture_setSmooth(IntPtr cPointer, bool smooth); + [DllImport(CSFML.Graphics, CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] + private static extern void sfRenderTexture_setSmooth(IntPtr cPointer, bool smooth); - [DllImport(CSFML.Graphics, CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] - [return: MarshalAs(UnmanagedType.I1)] - private static extern bool sfRenderTexture_isSmooth(IntPtr cPointer); + [DllImport(CSFML.Graphics, CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] + [return: MarshalAs(UnmanagedType.I1)] + private static extern bool sfRenderTexture_isSmooth(IntPtr cPointer); - [DllImport(CSFML.Graphics, CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] - private static extern void sfRenderTexture_setRepeated(IntPtr cPointer, bool repeated); + [DllImport(CSFML.Graphics, CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] + private static extern void sfRenderTexture_setRepeated(IntPtr cPointer, bool repeated); - [DllImport(CSFML.Graphics, CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] - [return: MarshalAs(UnmanagedType.I1)] - private static extern bool sfRenderTexture_isRepeated(IntPtr cPointer); + [DllImport(CSFML.Graphics, CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] + [return: MarshalAs(UnmanagedType.I1)] + private static extern bool sfRenderTexture_isRepeated(IntPtr cPointer); - [DllImport(CSFML.Graphics, CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] - [return: MarshalAs(UnmanagedType.I1)] - private static extern bool sfRenderTexture_generateMipmap(IntPtr cPointer); + [DllImport(CSFML.Graphics, CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] + [return: MarshalAs(UnmanagedType.I1)] + private static extern bool sfRenderTexture_generateMipmap(IntPtr cPointer); - [DllImport(CSFML.Graphics, CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] - private static extern unsafe void sfRenderTexture_drawPrimitives(IntPtr cPointer, Vertex* vertexPtr, UIntPtr vertexCount, PrimitiveType type, ref RenderStates.MarshalData renderStates); + [DllImport(CSFML.Graphics, CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] + private static extern unsafe void sfRenderTexture_drawPrimitives(IntPtr cPointer, Vertex* vertexPtr, UIntPtr vertexCount, PrimitiveType type, ref RenderStates.MarshalData renderStates); - [DllImport(CSFML.Graphics, CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] - private static extern void sfRenderTexture_pushGLStates(IntPtr cPointer); + [DllImport(CSFML.Graphics, CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] + private static extern void sfRenderTexture_pushGLStates(IntPtr cPointer); - [DllImport(CSFML.Graphics, CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] - private static extern void sfRenderTexture_popGLStates(IntPtr cPointer); + [DllImport(CSFML.Graphics, CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] + private static extern void sfRenderTexture_popGLStates(IntPtr cPointer); - [DllImport(CSFML.Graphics, CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] - private static extern void sfRenderTexture_resetGLStates(IntPtr cPointer); - #endregion - } + [DllImport(CSFML.Graphics, CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] + private static extern void sfRenderTexture_resetGLStates(IntPtr cPointer); + #endregion } diff --git a/src/SFML.Graphics/RenderWindow.cs b/src/SFML.Graphics/RenderWindow.cs index 4f784f0d..85324bb7 100644 --- a/src/SFML.Graphics/RenderWindow.cs +++ b/src/SFML.Graphics/RenderWindow.cs @@ -5,913 +5,912 @@ using SFML.System; using SFML.Window; -namespace SFML.Graphics +namespace SFML.Graphics; + +//////////////////////////////////////////////////////////// +/// +/// Simple wrapper for Window that allows easy +/// 2D rendering +/// +//////////////////////////////////////////////////////////// +public class RenderWindow : Window.Window, IRenderTarget { //////////////////////////////////////////////////////////// /// - /// Simple wrapper for Window that allows easy - /// 2D rendering + /// Create the window with default style, state and creation settings /// + /// Video mode to use + /// Title of the window //////////////////////////////////////////////////////////// - public class RenderWindow : Window.Window, IRenderTarget + public RenderWindow(VideoMode mode, string title) : + this(mode, title, Styles.Default, State.Windowed, new ContextSettings(0, 0)) { - //////////////////////////////////////////////////////////// - /// - /// Create the window with default style, state and creation settings - /// - /// Video mode to use - /// Title of the window - //////////////////////////////////////////////////////////// - public RenderWindow(VideoMode mode, string title) : - this(mode, title, Styles.Default, State.Windowed, new ContextSettings(0, 0)) - { - } + } - //////////////////////////////////////////////////////////// - /// - /// Create the window with default creation settings - /// - /// Video mode to use - /// Title of the window - /// Window style (Resize | Close by default) - /// Window state - //////////////////////////////////////////////////////////// - public RenderWindow(VideoMode mode, string title, Styles style, State state) : - this(mode, title, style, state, new ContextSettings(0, 0)) - { - } + //////////////////////////////////////////////////////////// + /// + /// Create the window with default creation settings + /// + /// Video mode to use + /// Title of the window + /// Window style (Resize | Close by default) + /// Window state + //////////////////////////////////////////////////////////// + public RenderWindow(VideoMode mode, string title, Styles style, State state) : + this(mode, title, style, state, new ContextSettings(0, 0)) + { + } - //////////////////////////////////////////////////////////// - /// - /// Create the window - /// - /// Video mode to use - /// Title of the window - /// Window style (Resize | Close by default) - /// Window state - /// Creation parameters - //////////////////////////////////////////////////////////// - public RenderWindow(VideoMode mode, string title, Styles style, State state, ContextSettings settings) : - base(IntPtr.Zero, 0) - { - // Copy the string to a null-terminated UTF-32 byte array - var titleAsUtf32 = Encoding.UTF32.GetBytes(title + '\0'); + //////////////////////////////////////////////////////////// + /// + /// Create the window + /// + /// Video mode to use + /// Title of the window + /// Window style (Resize | Close by default) + /// Window state + /// Creation parameters + //////////////////////////////////////////////////////////// + public RenderWindow(VideoMode mode, string title, Styles style, State state, ContextSettings settings) : + base(IntPtr.Zero, 0) + { + // Copy the string to a null-terminated UTF-32 byte array + var titleAsUtf32 = Encoding.UTF32.GetBytes(title + '\0'); - unsafe + unsafe + { + fixed (byte* titlePtr = titleAsUtf32) { - fixed (byte* titlePtr = titleAsUtf32) - { - CPointer = sfRenderWindow_createUnicode(mode, (IntPtr)titlePtr, style, state, ref settings); - } + CPointer = sfRenderWindow_createUnicode(mode, (IntPtr)titlePtr, style, state, ref settings); } - Initialize(); } + Initialize(); + } - //////////////////////////////////////////////////////////// - /// - /// Create the window from an existing control with default creation settings - /// - /// Platform-specific handle of the control - //////////////////////////////////////////////////////////// - public RenderWindow(IntPtr handle) : - this(handle, new ContextSettings(0, 0)) - { - } + //////////////////////////////////////////////////////////// + /// + /// Create the window from an existing control with default creation settings + /// + /// Platform-specific handle of the control + //////////////////////////////////////////////////////////// + public RenderWindow(IntPtr handle) : + this(handle, new ContextSettings(0, 0)) + { + } - //////////////////////////////////////////////////////////// - /// - /// Create the window from an existing control - /// - /// Platform-specific handle of the control - /// Creation parameters - //////////////////////////////////////////////////////////// - public RenderWindow(IntPtr handle, ContextSettings settings) : - base(sfRenderWindow_createFromHandle(handle, ref settings), 0) => Initialize(); - - //////////////////////////////////////////////////////////// - /// - /// Close (destroy) the window. - /// The Window instance remains valid and you can call - /// Create to recreate the window - /// - //////////////////////////////////////////////////////////// - public override void Close() => sfRenderWindow_close(CPointer); - - //////////////////////////////////////////////////////////// - /// - /// Tell whether or not the window is opened (ie. has been created). - /// Note that a hidden window (Show(false)) - /// will still return true - /// - /// True if the window is opened - //////////////////////////////////////////////////////////// - public override bool IsOpen => sfRenderWindow_isOpen(CPointer); - - //////////////////////////////////////////////////////////// - /// - /// Creation settings of the window - /// - //////////////////////////////////////////////////////////// - public override ContextSettings Settings => sfRenderWindow_getSettings(CPointer); - - //////////////////////////////////////////////////////////// - /// - /// Position of the window - /// - //////////////////////////////////////////////////////////// - public override Vector2i Position - { - get => sfRenderWindow_getPosition(CPointer); - set => sfRenderWindow_setPosition(CPointer, value); - } + //////////////////////////////////////////////////////////// + /// + /// Create the window from an existing control + /// + /// Platform-specific handle of the control + /// Creation parameters + //////////////////////////////////////////////////////////// + public RenderWindow(IntPtr handle, ContextSettings settings) : + base(sfRenderWindow_createFromHandle(handle, ref settings), 0) => Initialize(); - //////////////////////////////////////////////////////////// - /// - /// Size of the rendering region of the window - /// - //////////////////////////////////////////////////////////// - public override Vector2u Size - { - get => sfRenderWindow_getSize(CPointer); - set => sfRenderWindow_setSize(CPointer, value); - } + //////////////////////////////////////////////////////////// + /// + /// Close (destroy) the window. + /// The Window instance remains valid and you can call + /// Create to recreate the window + /// + //////////////////////////////////////////////////////////// + public override void Close() => sfRenderWindow_close(CPointer); + + //////////////////////////////////////////////////////////// + /// + /// Tell whether or not the window is opened (ie. has been created). + /// Note that a hidden window (Show(false)) + /// will still return true + /// + /// True if the window is opened + //////////////////////////////////////////////////////////// + public override bool IsOpen => sfRenderWindow_isOpen(CPointer); + + //////////////////////////////////////////////////////////// + /// + /// Creation settings of the window + /// + //////////////////////////////////////////////////////////// + public override ContextSettings Settings => sfRenderWindow_getSettings(CPointer); + + //////////////////////////////////////////////////////////// + /// + /// Position of the window + /// + //////////////////////////////////////////////////////////// + public override Vector2i Position + { + get => sfRenderWindow_getPosition(CPointer); + set => sfRenderWindow_setPosition(CPointer, value); + } + + //////////////////////////////////////////////////////////// + /// + /// Size of the rendering region of the window + /// + //////////////////////////////////////////////////////////// + public override Vector2u Size + { + get => sfRenderWindow_getSize(CPointer); + set => sfRenderWindow_setSize(CPointer, value); + } - //////////////////////////////////////////////////////////// - /// - /// Tell if the render window will use sRGB encoding when drawing on it - /// - //////////////////////////////////////////////////////////// - public bool IsSrgb => sfRenderWindow_isSrgb(CPointer); - - //////////////////////////////////////////////////////////// - /// - /// Set the minimum window rendering region size - /// - /// New minimum size, in pixels, null to reset the minimum size - //////////////////////////////////////////////////////////// - public override void SetMinimumSize(Vector2u? minimumSize) + //////////////////////////////////////////////////////////// + /// + /// Tell if the render window will use sRGB encoding when drawing on it + /// + //////////////////////////////////////////////////////////// + public bool IsSrgb => sfRenderWindow_isSrgb(CPointer); + + //////////////////////////////////////////////////////////// + /// + /// Set the minimum window rendering region size + /// + /// New minimum size, in pixels, null to reset the minimum size + //////////////////////////////////////////////////////////// + public override void SetMinimumSize(Vector2u? minimumSize) + { + unsafe { - unsafe + if (minimumSize.HasValue) { - if (minimumSize.HasValue) - { - var minimumSizeRef = minimumSize.Value; - sfRenderWindow_setMinimumSize(CPointer, &minimumSizeRef); - } - else - { - sfRenderWindow_setMinimumSize(CPointer, null); - } + var minimumSizeRef = minimumSize.Value; + sfRenderWindow_setMinimumSize(CPointer, &minimumSizeRef); } - } - - //////////////////////////////////////////////////////////// - /// - /// Set the maximum window rendering region size - /// - /// New maximum size, in pixels, null to reset the maximum size - //////////////////////////////////////////////////////////// - public override void SetMaximumSize(Vector2u? maximumSize) - { - unsafe + else { - if (maximumSize.HasValue) - { - var maximumSizeRef = maximumSize.Value; - sfRenderWindow_setMaximumSize(CPointer, &maximumSizeRef); - } - else - { - sfRenderWindow_setMaximumSize(CPointer, null); - } + sfRenderWindow_setMinimumSize(CPointer, null); } } + } - //////////////////////////////////////////////////////////// - /// - /// Change the title of the window - /// - /// New title - //////////////////////////////////////////////////////////// - public override void SetTitle(string title) + //////////////////////////////////////////////////////////// + /// + /// Set the maximum window rendering region size + /// + /// New maximum size, in pixels, null to reset the maximum size + //////////////////////////////////////////////////////////// + public override void SetMaximumSize(Vector2u? maximumSize) + { + unsafe { - // Copy the title to a null-terminated UTF-32 byte array - var titleAsUtf32 = Encoding.UTF32.GetBytes(title + '\0'); - - unsafe + if (maximumSize.HasValue) { - fixed (byte* titlePtr = titleAsUtf32) - { - sfRenderWindow_setUnicodeTitle(CPointer, (IntPtr)titlePtr); - } + var maximumSizeRef = maximumSize.Value; + sfRenderWindow_setMaximumSize(CPointer, &maximumSizeRef); + } + else + { + sfRenderWindow_setMaximumSize(CPointer, null); } } + } - //////////////////////////////////////////////////////////// - /// - /// Change the window's icon - /// - /// Icon's width and height, in pixels - /// Array of pixels, format must be RGBA 32 bits - //////////////////////////////////////////////////////////// - public override void SetIcon(Vector2u size, byte[] pixels) + //////////////////////////////////////////////////////////// + /// + /// Change the title of the window + /// + /// New title + //////////////////////////////////////////////////////////// + public override void SetTitle(string title) + { + // Copy the title to a null-terminated UTF-32 byte array + var titleAsUtf32 = Encoding.UTF32.GetBytes(title + '\0'); + + unsafe { - unsafe + fixed (byte* titlePtr = titleAsUtf32) { - fixed (byte* pixelsPtr = pixels) - { - sfRenderWindow_setIcon(CPointer, size, pixelsPtr); - } + sfRenderWindow_setUnicodeTitle(CPointer, (IntPtr)titlePtr); } } + } - //////////////////////////////////////////////////////////// - /// - /// Show or hide the window - /// - /// True to show the window, false to hide it - //////////////////////////////////////////////////////////// - public override void SetVisible(bool visible) => sfRenderWindow_setVisible(CPointer, visible); - - //////////////////////////////////////////////////////////// - /// - /// Enable / disable vertical synchronization - /// - /// True to enable v-sync, false to deactivate - //////////////////////////////////////////////////////////// - public override void SetVerticalSyncEnabled(bool enable) => sfRenderWindow_setVerticalSyncEnabled(CPointer, enable); - - //////////////////////////////////////////////////////////// - /// - /// Show or hide the mouse cursor - /// - /// True to show, false to hide - //////////////////////////////////////////////////////////// - public override void SetMouseCursorVisible(bool visible) => sfRenderWindow_setMouseCursorVisible(CPointer, visible); - - //////////////////////////////////////////////////////////// - /// - /// Grab or release the mouse cursor - /// - /// True to grab, false to release - /// - /// - /// If set, grabs the mouse cursor inside this window's client - /// area so it may no longer be moved outside its bounds. - /// Note that grabbing is only active while the window has - /// focus and calling this function for fullscreen windows - /// won't have any effect (fullscreen windows always grab the - /// cursor). - /// - //////////////////////////////////////////////////////////// - public override void SetMouseCursorGrabbed(bool grabbed) => sfRenderWindow_setMouseCursorGrabbed(CPointer, grabbed); - - //////////////////////////////////////////////////////////// - /// - /// Set the displayed cursor to a native system cursor - /// - /// Native system cursor type to display - //////////////////////////////////////////////////////////// - public override void SetMouseCursor(Cursor cursor) => sfRenderWindow_setMouseCursor(CPointer, cursor.CPointer); - - //////////////////////////////////////////////////////////// - /// - /// Enable or disable automatic key-repeat. - /// Automatic key-repeat is enabled by default - /// - /// True to enable, false to disable - //////////////////////////////////////////////////////////// - public override void SetKeyRepeatEnabled(bool enable) => sfRenderWindow_setKeyRepeatEnabled(CPointer, enable); - - //////////////////////////////////////////////////////////// - /// - /// Limit the framerate to a maximum fixed frequency - /// - /// Framerate limit, in frames per seconds (use 0 to disable limit) - //////////////////////////////////////////////////////////// - public override void SetFramerateLimit(uint limit) => sfRenderWindow_setFramerateLimit(CPointer, limit); - - //////////////////////////////////////////////////////////// - /// - /// Change the joystick threshold, ie. the value below which - /// no move event will be generated - /// - /// New threshold, in range [0, 100] - //////////////////////////////////////////////////////////// - public override void SetJoystickThreshold(float threshold) => sfRenderWindow_setJoystickThreshold(CPointer, threshold); - - //////////////////////////////////////////////////////////// - /// - /// Activate of deactivate the window as the current target - /// for rendering - /// - /// True to activate, false to deactivate (true by default) - /// True if operation was successful, false otherwise - //////////////////////////////////////////////////////////// - public override bool SetActive(bool active) => sfRenderWindow_setActive(CPointer, active); - - //////////////////////////////////////////////////////////// - /// - /// Request the current window to be made the active - /// foreground window - /// - //////////////////////////////////////////////////////////// - public override void RequestFocus() => sfRenderWindow_requestFocus(CPointer); - - //////////////////////////////////////////////////////////// - /// - /// Check whether the window has the input focus - /// - /// True if the window has focus, false otherwise - //////////////////////////////////////////////////////////// - public override bool HasFocus() => sfRenderWindow_hasFocus(CPointer); - - //////////////////////////////////////////////////////////// - /// - /// Create a Vulkan rendering surface - /// - /// Vulkan instance - /// Created surface - /// Allocator to use - /// True if surface creation was successful, false otherwise - //////////////////////////////////////////////////////////// - public override bool CreateVulkanSurface(IntPtr vkInstance, out IntPtr vkSurface, IntPtr vkAllocator) => sfRenderWindow_createVulkanSurface(CPointer, vkInstance, out vkSurface, vkAllocator); - - //////////////////////////////////////////////////////////// - /// - /// Display the window on screen - /// - //////////////////////////////////////////////////////////// - public override void Display() => sfRenderWindow_display(CPointer); - - //////////////////////////////////////////////////////////// - /// - /// OS-specific handle of the window - /// - //////////////////////////////////////////////////////////// - public override IntPtr NativeHandle => sfRenderWindow_getNativeHandle(CPointer); - - //////////////////////////////////////////////////////////// - /// - /// Clear the entire window with black color - /// - //////////////////////////////////////////////////////////// - public void Clear() => sfRenderWindow_clear(CPointer, Color.Black); - - //////////////////////////////////////////////////////////// - /// - /// Clear the entire window with a single color - /// - /// Color to use to clear the window - //////////////////////////////////////////////////////////// - public void Clear(Color color) => sfRenderWindow_clear(CPointer, color); - - //////////////////////////////////////////////////////////// - /// - /// 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. - /// - /// Fill color to use to clear the render target - /// Stencil value to clear to - //////////////////////////////////////////////////////////// - public void Clear(Color color, StencilValue stencilValue) => sfRenderWindow_clearColorAndStencil(CPointer, color, stencilValue); - - //////////////////////////////////////////////////////////// - /// - /// Clear the stencil buffer to a specific value - /// - /// The specified value is truncated to the bit width of - /// the current stencil buffer. - /// - /// Stencil value to clear to - //////////////////////////////////////////////////////////// - public void ClearStencil(StencilValue stencilValue) => sfRenderWindow_clearStencil(CPointer, stencilValue); - - - //////////////////////////////////////////////////////////// - /// - /// Change the current active view - /// - /// New view - //////////////////////////////////////////////////////////// - public void SetView(View view) => sfRenderWindow_setView(CPointer, view.CPointer); - - //////////////////////////////////////////////////////////// - /// - /// Return the current active view - /// - /// The current view - //////////////////////////////////////////////////////////// - public View GetView() => new View(sfRenderWindow_getView(CPointer)); - - //////////////////////////////////////////////////////////// - /// - /// Default view of the window - /// - //////////////////////////////////////////////////////////// - public View DefaultView => new View(_defaultView); - - //////////////////////////////////////////////////////////// - /// - /// Get the viewport of a view applied to this target - /// - /// Target view - /// Viewport rectangle, expressed in pixels in the current target - //////////////////////////////////////////////////////////// - public IntRect GetViewport(View view) => sfRenderWindow_getViewport(CPointer, view.CPointer); - - //////////////////////////////////////////////////////////// - /// - /// 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. - /// - /// The view for which we want to compute the scissor rectangle - /// Scissor rectangle, expressed in pixels - //////////////////////////////////////////////////////////// - public IntRect GetScissor(View view) => sfRenderWindow_getScissor(CPointer, view.CPointer); - - //////////////////////////////////////////////////////////// - /// - /// 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: - /// target.MapPixelToCoords(point, target.GetView()); - /// - /// Pixel to convert - /// The converted point, in "world" coordinates - //////////////////////////////////////////////////////////// - public Vector2f MapPixelToCoords(Vector2i point) => MapPixelToCoords(point, GetView()); - - //////////////////////////////////////////////////////////// - /// - /// 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, ie. 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. - /// - /// Pixel to convert - /// The view to use for converting the point - /// The converted point, in "world" coordinates - //////////////////////////////////////////////////////////// - public Vector2f MapPixelToCoords(Vector2i point, View view) => sfRenderWindow_mapPixelToCoords(CPointer, point, view != null ? view.CPointer : IntPtr.Zero); - - //////////////////////////////////////////////////////////// - /// - /// 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: - /// target.MapCoordsToPixel(point, target.GetView()); - /// - /// Point to convert - /// The converted point, in target coordinates (pixels) - //////////////////////////////////////////////////////////// - public Vector2i MapCoordsToPixel(Vector2f point) => MapCoordsToPixel(point, GetView()); - - //////////////////////////////////////////////////////////// - /// - /// 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, ie. 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. - /// - /// Point to convert - /// The view to use for converting the point - /// The converted point, in target coordinates (pixels) - //////////////////////////////////////////////////////////// - public Vector2i MapCoordsToPixel(Vector2f point, View view) => sfRenderWindow_mapCoordsToPixel(CPointer, point, view != null ? view.CPointer : IntPtr.Zero); - - //////////////////////////////////////////////////////////// - /// - /// Draw a drawable object to the render-target, with default render states - /// - /// Object to draw - //////////////////////////////////////////////////////////// - public void Draw(IDrawable drawable) => Draw(drawable, RenderStates.Default); - - //////////////////////////////////////////////////////////// - /// - /// Draw a drawable object to the render-target - /// - /// Object to draw - /// Render states to use for drawing - //////////////////////////////////////////////////////////// - public void Draw(IDrawable drawable, RenderStates states) => drawable.Draw(this, states); - - //////////////////////////////////////////////////////////// - /// - /// Draw primitives defined by an array of vertices, with default render states - /// - /// Pointer to the vertices - /// Type of primitives to draw - //////////////////////////////////////////////////////////// - public void Draw(Vertex[] vertices, PrimitiveType type) => Draw(vertices, type, RenderStates.Default); - - //////////////////////////////////////////////////////////// - /// - /// Draw primitives defined by an array of vertices - /// - /// Pointer to the vertices - /// Type of primitives to draw - /// Render states to use for drawing - //////////////////////////////////////////////////////////// - public void Draw(Vertex[] vertices, PrimitiveType type, RenderStates states) => Draw(vertices, 0, (uint)vertices.Length, type, states); - - //////////////////////////////////////////////////////////// - /// - /// Draw primitives defined by a sub-array of vertices, with default render states - /// - /// Array of vertices to draw - /// Index of the first vertex to draw in the array - /// Number of vertices to draw - /// Type of primitives to draw - //////////////////////////////////////////////////////////// - public void Draw(Vertex[] vertices, uint start, uint count, PrimitiveType type) => Draw(vertices, start, count, type, RenderStates.Default); - - //////////////////////////////////////////////////////////// - /// - /// Draw primitives defined by a sub-array of vertices - /// - /// Pointer to the vertices - /// Index of the first vertex to use in the array - /// Number of vertices to draw - /// Type of primitives to draw - /// Render states to use for drawing - //////////////////////////////////////////////////////////// - public void Draw(Vertex[] vertices, uint start, uint count, PrimitiveType type, RenderStates states) + //////////////////////////////////////////////////////////// + /// + /// Change the window's icon + /// + /// Icon's width and height, in pixels + /// Array of pixels, format must be RGBA 32 bits + //////////////////////////////////////////////////////////// + public override void SetIcon(Vector2u size, byte[] pixels) + { + unsafe { - var marshaledStates = states.Marshal(); - - unsafe + fixed (byte* pixelsPtr = pixels) { - fixed (Vertex* vertexPtr = vertices) - { - sfRenderWindow_drawPrimitives(CPointer, vertexPtr + start, (UIntPtr)count, type, ref marshaledStates); - } + sfRenderWindow_setIcon(CPointer, size, pixelsPtr); } } + } + + //////////////////////////////////////////////////////////// + /// + /// Show or hide the window + /// + /// True to show the window, false to hide it + //////////////////////////////////////////////////////////// + public override void SetVisible(bool visible) => sfRenderWindow_setVisible(CPointer, visible); + + //////////////////////////////////////////////////////////// + /// + /// Enable / disable vertical synchronization + /// + /// True to enable v-sync, false to deactivate + //////////////////////////////////////////////////////////// + public override void SetVerticalSyncEnabled(bool enable) => sfRenderWindow_setVerticalSyncEnabled(CPointer, enable); + + //////////////////////////////////////////////////////////// + /// + /// Show or hide the mouse cursor + /// + /// True to show, false to hide + //////////////////////////////////////////////////////////// + public override void SetMouseCursorVisible(bool visible) => sfRenderWindow_setMouseCursorVisible(CPointer, visible); + + //////////////////////////////////////////////////////////// + /// + /// Grab or release the mouse cursor + /// + /// True to grab, false to release + /// + /// + /// If set, grabs the mouse cursor inside this window's client + /// area so it may no longer be moved outside its bounds. + /// Note that grabbing is only active while the window has + /// focus and calling this function for fullscreen windows + /// won't have any effect (fullscreen windows always grab the + /// cursor). + /// + //////////////////////////////////////////////////////////// + public override void SetMouseCursorGrabbed(bool grabbed) => sfRenderWindow_setMouseCursorGrabbed(CPointer, grabbed); + + //////////////////////////////////////////////////////////// + /// + /// Set the displayed cursor to a native system cursor + /// + /// Native system cursor type to display + //////////////////////////////////////////////////////////// + public override void SetMouseCursor(Cursor cursor) => sfRenderWindow_setMouseCursor(CPointer, cursor.CPointer); + + //////////////////////////////////////////////////////////// + /// + /// Enable or disable automatic key-repeat. + /// Automatic key-repeat is enabled by default + /// + /// True to enable, false to disable + //////////////////////////////////////////////////////////// + public override void SetKeyRepeatEnabled(bool enable) => sfRenderWindow_setKeyRepeatEnabled(CPointer, enable); + + //////////////////////////////////////////////////////////// + /// + /// Limit the framerate to a maximum fixed frequency + /// + /// Framerate limit, in frames per seconds (use 0 to disable limit) + //////////////////////////////////////////////////////////// + public override void SetFramerateLimit(uint limit) => sfRenderWindow_setFramerateLimit(CPointer, limit); + + //////////////////////////////////////////////////////////// + /// + /// Change the joystick threshold, ie. the value below which + /// no move event will be generated + /// + /// New threshold, in range [0, 100] + //////////////////////////////////////////////////////////// + public override void SetJoystickThreshold(float threshold) => sfRenderWindow_setJoystickThreshold(CPointer, threshold); + + //////////////////////////////////////////////////////////// + /// + /// Activate of deactivate the window as the current target + /// for rendering + /// + /// True to activate, false to deactivate (true by default) + /// True if operation was successful, false otherwise + //////////////////////////////////////////////////////////// + public override bool SetActive(bool active) => sfRenderWindow_setActive(CPointer, active); + + //////////////////////////////////////////////////////////// + /// + /// Request the current window to be made the active + /// foreground window + /// + //////////////////////////////////////////////////////////// + public override void RequestFocus() => sfRenderWindow_requestFocus(CPointer); + + //////////////////////////////////////////////////////////// + /// + /// Check whether the window has the input focus + /// + /// True if the window has focus, false otherwise + //////////////////////////////////////////////////////////// + public override bool HasFocus() => sfRenderWindow_hasFocus(CPointer); + + //////////////////////////////////////////////////////////// + /// + /// Create a Vulkan rendering surface + /// + /// Vulkan instance + /// Created surface + /// Allocator to use + /// True if surface creation was successful, false otherwise + //////////////////////////////////////////////////////////// + public override bool CreateVulkanSurface(IntPtr vkInstance, out IntPtr vkSurface, IntPtr vkAllocator) => sfRenderWindow_createVulkanSurface(CPointer, vkInstance, out vkSurface, vkAllocator); + + //////////////////////////////////////////////////////////// + /// + /// Display the window on screen + /// + //////////////////////////////////////////////////////////// + public override void Display() => sfRenderWindow_display(CPointer); + + //////////////////////////////////////////////////////////// + /// + /// OS-specific handle of the window + /// + //////////////////////////////////////////////////////////// + public override IntPtr NativeHandle => sfRenderWindow_getNativeHandle(CPointer); + + //////////////////////////////////////////////////////////// + /// + /// Clear the entire window with black color + /// + //////////////////////////////////////////////////////////// + public void Clear() => sfRenderWindow_clear(CPointer, Color.Black); + + //////////////////////////////////////////////////////////// + /// + /// Clear the entire window with a single color + /// + /// Color to use to clear the window + //////////////////////////////////////////////////////////// + public void Clear(Color color) => sfRenderWindow_clear(CPointer, color); + + //////////////////////////////////////////////////////////// + /// + /// 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. + /// + /// Fill color to use to clear the render target + /// Stencil value to clear to + //////////////////////////////////////////////////////////// + public void Clear(Color color, StencilValue stencilValue) => sfRenderWindow_clearColorAndStencil(CPointer, color, stencilValue); + + //////////////////////////////////////////////////////////// + /// + /// Clear the stencil buffer to a specific value + /// + /// The specified value is truncated to the bit width of + /// the current stencil buffer. + /// + /// Stencil value to clear to + //////////////////////////////////////////////////////////// + public void ClearStencil(StencilValue stencilValue) => sfRenderWindow_clearStencil(CPointer, stencilValue); + + + //////////////////////////////////////////////////////////// + /// + /// Change the current active view + /// + /// New view + //////////////////////////////////////////////////////////// + public void SetView(View view) => sfRenderWindow_setView(CPointer, view.CPointer); + + //////////////////////////////////////////////////////////// + /// + /// Return the current active view + /// + /// The current view + //////////////////////////////////////////////////////////// + public View GetView() => new(sfRenderWindow_getView(CPointer)); + + //////////////////////////////////////////////////////////// + /// + /// Default view of the window + /// + //////////////////////////////////////////////////////////// + public View DefaultView => new(_defaultView); + + //////////////////////////////////////////////////////////// + /// + /// Get the viewport of a view applied to this target + /// + /// Target view + /// Viewport rectangle, expressed in pixels in the current target + //////////////////////////////////////////////////////////// + public IntRect GetViewport(View view) => sfRenderWindow_getViewport(CPointer, view.CPointer); + + //////////////////////////////////////////////////////////// + /// + /// 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. + /// + /// The view for which we want to compute the scissor rectangle + /// Scissor rectangle, expressed in pixels + //////////////////////////////////////////////////////////// + public IntRect GetScissor(View view) => sfRenderWindow_getScissor(CPointer, view.CPointer); + + //////////////////////////////////////////////////////////// + /// + /// 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: + /// target.MapPixelToCoords(point, target.GetView()); + /// + /// Pixel to convert + /// The converted point, in "world" coordinates + //////////////////////////////////////////////////////////// + public Vector2f MapPixelToCoords(Vector2i point) => MapPixelToCoords(point, GetView()); + + //////////////////////////////////////////////////////////// + /// + /// 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, ie. 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. + /// + /// Pixel to convert + /// The view to use for converting the point + /// The converted point, in "world" coordinates + //////////////////////////////////////////////////////////// + public Vector2f MapPixelToCoords(Vector2i point, View view) => sfRenderWindow_mapPixelToCoords(CPointer, point, view?.CPointer ?? IntPtr.Zero); + + //////////////////////////////////////////////////////////// + /// + /// 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: + /// target.MapCoordsToPixel(point, target.GetView()); + /// + /// Point to convert + /// The converted point, in target coordinates (pixels) + //////////////////////////////////////////////////////////// + public Vector2i MapCoordsToPixel(Vector2f point) => MapCoordsToPixel(point, GetView()); + + //////////////////////////////////////////////////////////// + /// + /// 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, ie. 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. + /// + /// Point to convert + /// The view to use for converting the point + /// The converted point, in target coordinates (pixels) + //////////////////////////////////////////////////////////// + public Vector2i MapCoordsToPixel(Vector2f point, View view) => sfRenderWindow_mapCoordsToPixel(CPointer, point, view?.CPointer ?? IntPtr.Zero); + + //////////////////////////////////////////////////////////// + /// + /// Draw a drawable object to the render-target, with default render states + /// + /// Object to draw + //////////////////////////////////////////////////////////// + public void Draw(IDrawable drawable) => Draw(drawable, RenderStates.Default); + + //////////////////////////////////////////////////////////// + /// + /// Draw a drawable object to the render-target + /// + /// Object to draw + /// Render states to use for drawing + //////////////////////////////////////////////////////////// + public void Draw(IDrawable drawable, RenderStates states) => drawable.Draw(this, states); + + //////////////////////////////////////////////////////////// + /// + /// Draw primitives defined by an array of vertices, with default render states + /// + /// Pointer to the vertices + /// Type of primitives to draw + //////////////////////////////////////////////////////////// + public void Draw(Vertex[] vertices, PrimitiveType type) => Draw(vertices, type, RenderStates.Default); - //////////////////////////////////////////////////////////// - /// - /// Save the current OpenGL render states and matrices. - /// - /// - /// - /// // OpenGL code here... - /// window.PushGLStates(); - /// window.Draw(...); - /// window.Draw(...); - /// window.PopGLStates(); - /// // OpenGL code here... - /// - /// - /// - /// This function can be used when you mix SFML drawing - /// and direct OpenGL rendering. Combined with PopGLStates, - /// it ensures that: - /// SFML's internal states are not messed up by your OpenGL code - /// 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. - /// - /// 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 - /// function if you do so. - /// - //////////////////////////////////////////////////////////// - public void PushGLStates() => sfRenderWindow_pushGLStates(CPointer); - - //////////////////////////////////////////////////////////// - /// - /// Restore the previously saved OpenGL render states and matrices. - /// - /// See the description of to get a detailed - /// description of these functions. - /// - //////////////////////////////////////////////////////////// - public void PopGLStates() => sfRenderWindow_popGLStates(CPointer); - - //////////////////////////////////////////////////////////// - /// - /// 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. - /// - /// - /// - /// // OpenGL code here... - /// glPushAttrib(...); - /// window.ResetGLStates(); - /// window.Draw(...); - /// window.Draw(...); - /// glPopAttrib(...); - /// // OpenGL code here... - /// - //////////////////////////////////////////////////////////// - public void ResetGLStates() => sfRenderWindow_resetGLStates(CPointer); - - //////////////////////////////////////////////////////////// - /// - /// Provide a string describing the object - /// - /// String description of the object - //////////////////////////////////////////////////////////// - public override string ToString() + //////////////////////////////////////////////////////////// + /// + /// Draw primitives defined by an array of vertices + /// + /// Pointer to the vertices + /// Type of primitives to draw + /// Render states to use for drawing + //////////////////////////////////////////////////////////// + public void Draw(Vertex[] vertices, PrimitiveType type, RenderStates states) => Draw(vertices, 0, (uint)vertices.Length, type, states); + + //////////////////////////////////////////////////////////// + /// + /// Draw primitives defined by a sub-array of vertices, with default render states + /// + /// Array of vertices to draw + /// Index of the first vertex to draw in the array + /// Number of vertices to draw + /// Type of primitives to draw + //////////////////////////////////////////////////////////// + public void Draw(Vertex[] vertices, uint start, uint count, PrimitiveType type) => Draw(vertices, start, count, type, RenderStates.Default); + + //////////////////////////////////////////////////////////// + /// + /// Draw primitives defined by a sub-array of vertices + /// + /// Pointer to the vertices + /// Index of the first vertex to use in the array + /// Number of vertices to draw + /// Type of primitives to draw + /// Render states to use for drawing + //////////////////////////////////////////////////////////// + public void Draw(Vertex[] vertices, uint start, uint count, PrimitiveType type, RenderStates states) + { + var marshaledStates = states.Marshal(); + + unsafe { - if (IsInvalid) + fixed (Vertex* vertexPtr = vertices) { - return MakeDisposedObjectString(); + sfRenderWindow_drawPrimitives(CPointer, vertexPtr + start, (UIntPtr)count, type, ref marshaledStates); } - - return "[RenderWindow]" + - " Size(" + Size + ")" + - " Position(" + Position + ")" + - " Settings(" + Settings + ")" + - " DefaultView(" + DefaultView + ")" + - " View(" + GetView() + ")"; } + } - //////////////////////////////////////////////////////////// - /// - /// Internal function to get the next event - /// - /// Variable to fill with the raw pointer to the event structure - /// True if there was an event, false otherwise - //////////////////////////////////////////////////////////// - protected override bool PollEvent(out Event eventToFill) => sfRenderWindow_pollEvent(CPointer, out eventToFill); - - //////////////////////////////////////////////////////////// - /// - /// Internal function to get the next event (blocking) - /// - /// Maximum time to wait ( for infinite) - /// Variable to fill with the raw pointer to the event structure - /// False if any error occurred - //////////////////////////////////////////////////////////// - protected override bool WaitEvent(Time timeout, out Event eventToFill) => sfRenderWindow_waitEvent(CPointer, timeout, out eventToFill); - - //////////////////////////////////////////////////////////// - /// - /// Internal function to get the mouse position relative to the window. - /// This function is protected because it is called by another class, - /// it is not meant to be called by users. - /// - /// Relative mouse position - //////////////////////////////////////////////////////////// - protected override Vector2i InternalGetMousePosition() => sfMouse_getPositionRenderWindow(CPointer); - - //////////////////////////////////////////////////////////// - /// - /// Internal function to set the mouse position relative to the window. - /// This function is protected because it is called by another class, - /// it is not meant to be called by users. - /// - /// Relative mouse position - //////////////////////////////////////////////////////////// - protected override void InternalSetMousePosition(Vector2i position) => sfMouse_setPositionRenderWindow(position, CPointer); - - //////////////////////////////////////////////////////////// - /// - /// Internal function to get the touch position relative to the window. - /// This function is protected because it is called by another class of - /// another module, it is not meant to be called by users. - /// - /// Finger index - /// Relative touch position - //////////////////////////////////////////////////////////// - protected override Vector2i InternalGetTouchPosition(uint finger) => sfTouch_getPositionRenderWindow(finger, CPointer); - - //////////////////////////////////////////////////////////// - /// - /// Handle the destruction of the object - /// - /// Is the GC disposing the object, or is it an explicit call ? - //////////////////////////////////////////////////////////// - protected override void Destroy(bool disposing) - { - sfRenderWindow_destroy(CPointer); + //////////////////////////////////////////////////////////// + /// + /// Save the current OpenGL render states and matrices. + /// + /// + /// + /// // OpenGL code here... + /// window.PushGLStates(); + /// window.Draw(...); + /// window.Draw(...); + /// window.PopGLStates(); + /// // OpenGL code here... + /// + /// + /// + /// This function can be used when you mix SFML drawing + /// and direct OpenGL rendering. Combined with PopGLStates, + /// it ensures that: + /// SFML's internal states are not messed up by your OpenGL code + /// 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. + /// + /// 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 + /// function if you do so. + /// + //////////////////////////////////////////////////////////// + public void PushGLStates() => sfRenderWindow_pushGLStates(CPointer); - if (disposing) - { - _defaultView.Dispose(); - } + //////////////////////////////////////////////////////////// + /// + /// Restore the previously saved OpenGL render states and matrices. + /// + /// See the description of to get a detailed + /// description of these functions. + /// + //////////////////////////////////////////////////////////// + public void PopGLStates() => sfRenderWindow_popGLStates(CPointer); - _defaultView = null; + //////////////////////////////////////////////////////////// + /// + /// 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. + /// + /// + /// + /// // OpenGL code here... + /// glPushAttrib(...); + /// window.ResetGLStates(); + /// window.Draw(...); + /// window.Draw(...); + /// glPopAttrib(...); + /// // OpenGL code here... + /// + //////////////////////////////////////////////////////////// + public void ResetGLStates() => sfRenderWindow_resetGLStates(CPointer); + + //////////////////////////////////////////////////////////// + /// + /// Provide a string describing the object + /// + /// String description of the object + //////////////////////////////////////////////////////////// + public override string ToString() + { + if (IsInvalid) + { + return MakeDisposedObjectString(); } - //////////////////////////////////////////////////////////// - /// - /// Do common initializations - /// - //////////////////////////////////////////////////////////// - private void Initialize() + return "[RenderWindow]" + + " Size(" + Size + ")" + + " Position(" + Position + ")" + + " Settings(" + Settings + ")" + + " DefaultView(" + DefaultView + ")" + + " View(" + GetView() + ")"; + } + + //////////////////////////////////////////////////////////// + /// + /// Internal function to get the next event + /// + /// Variable to fill with the raw pointer to the event structure + /// True if there was an event, false otherwise + //////////////////////////////////////////////////////////// + protected override bool PollEvent(out Event eventToFill) => sfRenderWindow_pollEvent(CPointer, out eventToFill); + + //////////////////////////////////////////////////////////// + /// + /// Internal function to get the next event (blocking) + /// + /// Maximum time to wait ( for infinite) + /// Variable to fill with the raw pointer to the event structure + /// False if any error occurred + //////////////////////////////////////////////////////////// + protected override bool WaitEvent(Time timeout, out Event eventToFill) => sfRenderWindow_waitEvent(CPointer, timeout, out eventToFill); + + //////////////////////////////////////////////////////////// + /// + /// Internal function to get the mouse position relative to the window. + /// This function is protected because it is called by another class, + /// it is not meant to be called by users. + /// + /// Relative mouse position + //////////////////////////////////////////////////////////// + protected override Vector2i InternalGetMousePosition() => sfMouse_getPositionRenderWindow(CPointer); + + //////////////////////////////////////////////////////////// + /// + /// Internal function to set the mouse position relative to the window. + /// This function is protected because it is called by another class, + /// it is not meant to be called by users. + /// + /// Relative mouse position + //////////////////////////////////////////////////////////// + protected override void InternalSetMousePosition(Vector2i position) => sfMouse_setPositionRenderWindow(position, CPointer); + + //////////////////////////////////////////////////////////// + /// + /// Internal function to get the touch position relative to the window. + /// This function is protected because it is called by another class of + /// another module, it is not meant to be called by users. + /// + /// Finger index + /// Relative touch position + //////////////////////////////////////////////////////////// + protected override Vector2i InternalGetTouchPosition(uint finger) => sfTouch_getPositionRenderWindow(finger, CPointer); + + //////////////////////////////////////////////////////////// + /// + /// Handle the destruction of the object + /// + /// Is the GC disposing the object, or is it an explicit call ? + //////////////////////////////////////////////////////////// + protected override void Destroy(bool disposing) + { + sfRenderWindow_destroy(CPointer); + + if (disposing) { - _defaultView = new View(sfRenderWindow_getDefaultView(CPointer)); - GC.SuppressFinalize(_defaultView); + _defaultView.Dispose(); } - private View _defaultView; + _defaultView = null; + } + + //////////////////////////////////////////////////////////// + /// + /// Do common initializations + /// + //////////////////////////////////////////////////////////// + private void Initialize() + { + _defaultView = new View(sfRenderWindow_getDefaultView(CPointer)); + GC.SuppressFinalize(_defaultView); + } - #region Imports - [DllImport(CSFML.Graphics, CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] - private static extern IntPtr sfRenderWindow_createUnicode(VideoMode mode, IntPtr title, Styles style, State state, ref ContextSettings settings); + private View _defaultView; - [DllImport(CSFML.Graphics, CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] - private static extern IntPtr sfRenderWindow_createFromHandle(IntPtr handle, ref ContextSettings settings); + #region Imports + [DllImport(CSFML.Graphics, CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] + private static extern IntPtr sfRenderWindow_createUnicode(VideoMode mode, IntPtr title, Styles style, State state, ref ContextSettings settings); - [DllImport(CSFML.Graphics, CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] - private static extern void sfRenderWindow_destroy(IntPtr cPointer); + [DllImport(CSFML.Graphics, CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] + private static extern IntPtr sfRenderWindow_createFromHandle(IntPtr handle, ref ContextSettings settings); - [DllImport(CSFML.Graphics, CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] - private static extern void sfRenderWindow_close(IntPtr cPointer); + [DllImport(CSFML.Graphics, CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] + private static extern void sfRenderWindow_destroy(IntPtr cPointer); - [DllImport(CSFML.Graphics, CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] - [return: MarshalAs(UnmanagedType.I1)] - private static extern bool sfRenderWindow_isOpen(IntPtr cPointer); + [DllImport(CSFML.Graphics, CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] + private static extern void sfRenderWindow_close(IntPtr cPointer); - [DllImport(CSFML.Graphics, CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] - private static extern ContextSettings sfRenderWindow_getSettings(IntPtr cPointer); + [DllImport(CSFML.Graphics, CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] + [return: MarshalAs(UnmanagedType.I1)] + private static extern bool sfRenderWindow_isOpen(IntPtr cPointer); - [DllImport(CSFML.Graphics, CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] - [return: MarshalAs(UnmanagedType.I1)] - private static extern bool sfRenderWindow_pollEvent(IntPtr cPointer, out Event evt); + [DllImport(CSFML.Graphics, CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] + private static extern ContextSettings sfRenderWindow_getSettings(IntPtr cPointer); - [DllImport(CSFML.Graphics, CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] - [return: MarshalAs(UnmanagedType.I1)] - private static extern bool sfRenderWindow_waitEvent(IntPtr cPointer, Time timeout, out Event evt); + [DllImport(CSFML.Graphics, CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] + [return: MarshalAs(UnmanagedType.I1)] + private static extern bool sfRenderWindow_pollEvent(IntPtr cPointer, out Event evt); - [DllImport(CSFML.Graphics, CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] - private static extern Vector2i sfRenderWindow_getPosition(IntPtr cPointer); + [DllImport(CSFML.Graphics, CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] + [return: MarshalAs(UnmanagedType.I1)] + private static extern bool sfRenderWindow_waitEvent(IntPtr cPointer, Time timeout, out Event evt); - [DllImport(CSFML.Graphics, CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] - private static extern void sfRenderWindow_setPosition(IntPtr cPointer, Vector2i position); + [DllImport(CSFML.Graphics, CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] + private static extern Vector2i sfRenderWindow_getPosition(IntPtr cPointer); - [DllImport(CSFML.Graphics, CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] - private static extern Vector2u sfRenderWindow_getSize(IntPtr cPointer); + [DllImport(CSFML.Graphics, CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] + private static extern void sfRenderWindow_setPosition(IntPtr cPointer, Vector2i position); - [DllImport(CSFML.Graphics, CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] - [return: MarshalAs(UnmanagedType.I1)] - private static extern bool sfRenderWindow_isSrgb(IntPtr cPointer); + [DllImport(CSFML.Graphics, CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] + private static extern Vector2u sfRenderWindow_getSize(IntPtr cPointer); - [DllImport(CSFML.Graphics, CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] - private static extern void sfRenderWindow_setSize(IntPtr cPointer, Vector2u size); + [DllImport(CSFML.Graphics, CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] + [return: MarshalAs(UnmanagedType.I1)] + private static extern bool sfRenderWindow_isSrgb(IntPtr cPointer); - [DllImport(CSFML.Graphics, CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] - private static extern unsafe void sfRenderWindow_setMinimumSize(IntPtr cPointer, Vector2u* minimumSize); + [DllImport(CSFML.Graphics, CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] + private static extern void sfRenderWindow_setSize(IntPtr cPointer, Vector2u size); - [DllImport(CSFML.Graphics, CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] - private static extern unsafe void sfRenderWindow_setMaximumSize(IntPtr cPointer, Vector2u* maximumSize); + [DllImport(CSFML.Graphics, CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] + private static extern unsafe void sfRenderWindow_setMinimumSize(IntPtr cPointer, Vector2u* minimumSize); - [DllImport(CSFML.Graphics, CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] - private static extern void sfRenderWindow_setUnicodeTitle(IntPtr cPointer, IntPtr title); + [DllImport(CSFML.Graphics, CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] + private static extern unsafe void sfRenderWindow_setMaximumSize(IntPtr cPointer, Vector2u* maximumSize); - [DllImport(CSFML.Graphics, CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] - private static extern unsafe void sfRenderWindow_setIcon(IntPtr cPointer, Vector2u size, byte* pixels); + [DllImport(CSFML.Graphics, CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] + private static extern void sfRenderWindow_setUnicodeTitle(IntPtr cPointer, IntPtr title); - [DllImport(CSFML.Graphics, CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] - private static extern void sfRenderWindow_setVisible(IntPtr cPointer, bool visible); + [DllImport(CSFML.Graphics, CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] + private static extern unsafe void sfRenderWindow_setIcon(IntPtr cPointer, Vector2u size, byte* pixels); - [DllImport(CSFML.Graphics, CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] - private static extern void sfRenderWindow_setVerticalSyncEnabled(IntPtr cPointer, bool enable); + [DllImport(CSFML.Graphics, CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] + private static extern void sfRenderWindow_setVisible(IntPtr cPointer, bool visible); - [DllImport(CSFML.Graphics, CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] - private static extern void sfRenderWindow_setMouseCursorVisible(IntPtr cPointer, bool visible); + [DllImport(CSFML.Graphics, CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] + private static extern void sfRenderWindow_setVerticalSyncEnabled(IntPtr cPointer, bool enable); - [DllImport(CSFML.Graphics, CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] - private static extern void sfRenderWindow_setMouseCursorGrabbed(IntPtr cPointer, bool grabbed); + [DllImport(CSFML.Graphics, CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] + private static extern void sfRenderWindow_setMouseCursorVisible(IntPtr cPointer, bool visible); - [DllImport(CSFML.Graphics, CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] - private static extern void sfRenderWindow_setMouseCursor(IntPtr window, IntPtr cursor); + [DllImport(CSFML.Graphics, CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] + private static extern void sfRenderWindow_setMouseCursorGrabbed(IntPtr cPointer, bool grabbed); - [DllImport(CSFML.Graphics, CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] - private static extern void sfRenderWindow_setKeyRepeatEnabled(IntPtr cPointer, bool enable); + [DllImport(CSFML.Graphics, CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] + private static extern void sfRenderWindow_setMouseCursor(IntPtr window, IntPtr cursor); - [DllImport(CSFML.Graphics, CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] - private static extern void sfRenderWindow_setFramerateLimit(IntPtr cPointer, uint limit); + [DllImport(CSFML.Graphics, CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] + private static extern void sfRenderWindow_setKeyRepeatEnabled(IntPtr cPointer, bool enable); - [DllImport(CSFML.Graphics, CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] - private static extern void sfRenderWindow_setJoystickThreshold(IntPtr cPointer, float threshold); + [DllImport(CSFML.Graphics, CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] + private static extern void sfRenderWindow_setFramerateLimit(IntPtr cPointer, uint limit); - [DllImport(CSFML.Graphics, CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] - [return: MarshalAs(UnmanagedType.I1)] - private static extern bool sfRenderWindow_setActive(IntPtr cPointer, bool active); + [DllImport(CSFML.Graphics, CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] + private static extern void sfRenderWindow_setJoystickThreshold(IntPtr cPointer, float threshold); - [DllImport(CSFML.Graphics, CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] - private static extern void sfRenderWindow_requestFocus(IntPtr cPointer); + [DllImport(CSFML.Graphics, CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] + [return: MarshalAs(UnmanagedType.I1)] + private static extern bool sfRenderWindow_setActive(IntPtr cPointer, bool active); - [DllImport(CSFML.Graphics, CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] - [return: MarshalAs(UnmanagedType.I1)] - private static extern bool sfRenderWindow_hasFocus(IntPtr cPointer); + [DllImport(CSFML.Graphics, CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] + private static extern void sfRenderWindow_requestFocus(IntPtr cPointer); - [DllImport(CSFML.Graphics, CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] - private static extern void sfRenderWindow_display(IntPtr cPointer); + [DllImport(CSFML.Graphics, CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] + [return: MarshalAs(UnmanagedType.I1)] + private static extern bool sfRenderWindow_hasFocus(IntPtr cPointer); - [DllImport(CSFML.Graphics, CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] - private static extern IntPtr sfRenderWindow_getNativeHandle(IntPtr cPointer); + [DllImport(CSFML.Graphics, CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] + private static extern void sfRenderWindow_display(IntPtr cPointer); - [DllImport(CSFML.Graphics, CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] - private static extern void sfRenderWindow_clear(IntPtr cPointer, Color clearColor); + [DllImport(CSFML.Graphics, CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] + private static extern IntPtr sfRenderWindow_getNativeHandle(IntPtr cPointer); - [DllImport(CSFML.Graphics, CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] - private static extern void sfRenderWindow_clearStencil(IntPtr cPointer, StencilValue stencilValue); + [DllImport(CSFML.Graphics, CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] + private static extern void sfRenderWindow_clear(IntPtr cPointer, Color clearColor); - [DllImport(CSFML.Graphics, CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] - private static extern void sfRenderWindow_clearColorAndStencil(IntPtr cPointer, Color clearColor, StencilValue stencilValue); + [DllImport(CSFML.Graphics, CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] + private static extern void sfRenderWindow_clearStencil(IntPtr cPointer, StencilValue stencilValue); - [DllImport(CSFML.Graphics, CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] - private static extern void sfRenderWindow_setView(IntPtr cPointer, IntPtr view); + [DllImport(CSFML.Graphics, CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] + private static extern void sfRenderWindow_clearColorAndStencil(IntPtr cPointer, Color clearColor, StencilValue stencilValue); - [DllImport(CSFML.Graphics, CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] - private static extern IntPtr sfRenderWindow_getView(IntPtr cPointer); + [DllImport(CSFML.Graphics, CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] + private static extern void sfRenderWindow_setView(IntPtr cPointer, IntPtr view); - [DllImport(CSFML.Graphics, CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] - private static extern IntPtr sfRenderWindow_getDefaultView(IntPtr cPointer); + [DllImport(CSFML.Graphics, CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] + private static extern IntPtr sfRenderWindow_getView(IntPtr cPointer); - [DllImport(CSFML.Graphics, CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] - private static extern IntRect sfRenderWindow_getViewport(IntPtr cPointer, IntPtr targetView); + [DllImport(CSFML.Graphics, CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] + private static extern IntPtr sfRenderWindow_getDefaultView(IntPtr cPointer); - [DllImport(CSFML.Graphics, CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] - private static extern IntRect sfRenderWindow_getScissor(IntPtr cPointer, IntPtr targetView); + [DllImport(CSFML.Graphics, CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] + private static extern IntRect sfRenderWindow_getViewport(IntPtr cPointer, IntPtr targetView); - [DllImport(CSFML.Graphics, CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] - private static extern Vector2f sfRenderWindow_mapPixelToCoords(IntPtr cPointer, Vector2i point, IntPtr view); + [DllImport(CSFML.Graphics, CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] + private static extern IntRect sfRenderWindow_getScissor(IntPtr cPointer, IntPtr targetView); - [DllImport(CSFML.Graphics, CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] - private static extern Vector2i sfRenderWindow_mapCoordsToPixel(IntPtr cPointer, Vector2f point, IntPtr view); + [DllImport(CSFML.Graphics, CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] + private static extern Vector2f sfRenderWindow_mapPixelToCoords(IntPtr cPointer, Vector2i point, IntPtr view); - [DllImport(CSFML.Graphics, CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] - private static extern unsafe void sfRenderWindow_drawPrimitives(IntPtr cPointer, Vertex* vertexPtr, UIntPtr vertexCount, PrimitiveType type, ref RenderStates.MarshalData renderStates); + [DllImport(CSFML.Graphics, CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] + private static extern Vector2i sfRenderWindow_mapCoordsToPixel(IntPtr cPointer, Vector2f point, IntPtr view); - [DllImport(CSFML.Graphics, CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] - private static extern void sfRenderWindow_pushGLStates(IntPtr cPointer); + [DllImport(CSFML.Graphics, CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] + private static extern unsafe void sfRenderWindow_drawPrimitives(IntPtr cPointer, Vertex* vertexPtr, UIntPtr vertexCount, PrimitiveType type, ref RenderStates.MarshalData renderStates); - [DllImport(CSFML.Graphics, CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] - private static extern void sfRenderWindow_popGLStates(IntPtr cPointer); + [DllImport(CSFML.Graphics, CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] + private static extern void sfRenderWindow_pushGLStates(IntPtr cPointer); - [DllImport(CSFML.Graphics, CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] - private static extern void sfRenderWindow_resetGLStates(IntPtr cPointer); + [DllImport(CSFML.Graphics, CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] + private static extern void sfRenderWindow_popGLStates(IntPtr cPointer); - [DllImport(CSFML.Graphics, CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] - private static extern Vector2i sfMouse_getPositionRenderWindow(IntPtr cPointer); + [DllImport(CSFML.Graphics, CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] + private static extern void sfRenderWindow_resetGLStates(IntPtr cPointer); - [DllImport(CSFML.Graphics, CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] - private static extern void sfMouse_setPositionRenderWindow(Vector2i position, IntPtr cPointer); + [DllImport(CSFML.Graphics, CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] + private static extern Vector2i sfMouse_getPositionRenderWindow(IntPtr cPointer); - [DllImport(CSFML.Graphics, CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] - private static extern Vector2i sfTouch_getPositionRenderWindow(uint finger, IntPtr relativeTo); + [DllImport(CSFML.Graphics, CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] + private static extern void sfMouse_setPositionRenderWindow(Vector2i position, IntPtr cPointer); - [DllImport(CSFML.Graphics, CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] - [return: MarshalAs(UnmanagedType.I1)] - private static extern bool sfRenderWindow_createVulkanSurface(IntPtr cPointer, IntPtr vkInstance, out IntPtr surface, IntPtr vkAllocator); - #endregion - } + [DllImport(CSFML.Graphics, CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] + private static extern Vector2i sfTouch_getPositionRenderWindow(uint finger, IntPtr relativeTo); + + [DllImport(CSFML.Graphics, CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] + [return: MarshalAs(UnmanagedType.I1)] + private static extern bool sfRenderWindow_createVulkanSurface(IntPtr cPointer, IntPtr vkInstance, out IntPtr surface, IntPtr vkAllocator); + #endregion } diff --git a/src/SFML.Graphics/Shader.cs b/src/SFML.Graphics/Shader.cs index 78627bb2..d3c6048c 100644 --- a/src/SFML.Graphics/Shader.cs +++ b/src/SFML.Graphics/Shader.cs @@ -6,618 +6,617 @@ using SFML.System; using SFML.Window; -namespace SFML.Graphics +namespace SFML.Graphics; + +//////////////////////////////////////////////////////////// +/// +/// Wrapper for pixel shaders +/// +//////////////////////////////////////////////////////////// +public class Shader : ObjectBase { //////////////////////////////////////////////////////////// /// - /// Wrapper for pixel shaders + /// Special type that can be passed to SetParameter, + /// and that represents the texture of the object being drawn /// //////////////////////////////////////////////////////////// - public class Shader : ObjectBase + public class CurrentTextureType { } + + //////////////////////////////////////////////////////////// + /// + /// Special value that can be passed to SetParameter, + /// and that represents the texture of the object being drawn + /// + //////////////////////////////////////////////////////////// + public static readonly CurrentTextureType CurrentTexture; + + //////////////////////////////////////////////////////////// + /// + /// Load the vertex, geometry and fragment shaders from files + /// + /// + /// This function loads the vertex, geometry and fragment + /// shaders. Pass NULL if you don't want to load + /// a specific shader. + /// The sources must be text files containing valid shaders + /// in GLSL language. GLSL is a C-like language dedicated to + /// OpenGL shaders; you'll probably need to read a good documentation + /// for it before writing your own shaders. + /// + /// Path of the vertex shader file to load, or null to skip this shader + /// Path of the geometry shader file to load, or null to skip this shader + /// Path of the fragment shader file to load, or null to skip this shader + /// + //////////////////////////////////////////////////////////// + public Shader(string vertexShaderFilename, string geometryShaderFilename, string fragmentShaderFilename) : + base(sfShader_createFromFile(vertexShaderFilename, geometryShaderFilename, fragmentShaderFilename)) { - //////////////////////////////////////////////////////////// - /// - /// Special type that can be passed to SetParameter, - /// and that represents the texture of the object being drawn - /// - //////////////////////////////////////////////////////////// - public class CurrentTextureType { } - - //////////////////////////////////////////////////////////// - /// - /// Special value that can be passed to SetParameter, - /// and that represents the texture of the object being drawn - /// - //////////////////////////////////////////////////////////// - public static readonly CurrentTextureType CurrentTexture; - - //////////////////////////////////////////////////////////// - /// - /// Load the vertex, geometry and fragment shaders from files - /// - /// - /// This function loads the vertex, geometry and fragment - /// shaders. Pass NULL if you don't want to load - /// a specific shader. - /// The sources must be text files containing valid shaders - /// in GLSL language. GLSL is a C-like language dedicated to - /// OpenGL shaders; you'll probably need to read a good documentation - /// for it before writing your own shaders. - /// - /// Path of the vertex shader file to load, or null to skip this shader - /// Path of the geometry shader file to load, or null to skip this shader - /// Path of the fragment shader file to load, or null to skip this shader - /// - //////////////////////////////////////////////////////////// - public Shader(string vertexShaderFilename, string geometryShaderFilename, string fragmentShaderFilename) : - base(sfShader_createFromFile(vertexShaderFilename, geometryShaderFilename, fragmentShaderFilename)) + if (IsInvalid) { - if (IsInvalid) - { - throw new LoadingFailedException("shader", vertexShaderFilename + " " + fragmentShaderFilename); - } + throw new LoadingFailedException("shader", vertexShaderFilename + " " + fragmentShaderFilename); } + } - //////////////////////////////////////////////////////////// - /// - /// Load the vertex, geometry and fragment shaders from custom streams - /// - /// - /// - /// This function loads the vertex, geometry and fragment - /// shaders. Pass NULL if you don't want to load - /// a specific shader. - /// The sources must be valid shaders in GLSL language. GLSL is - /// a C-like language dedicated to OpenGL shaders; you'll - /// probably need to read a good documentation for it before - /// writing your own shaders. - /// - /// Source stream to read the vertex shader from, or null to skip this shader - /// Source stream to read the geometry shader from, or null to skip this shader - /// Source stream to read the fragment shader from, or null to skip this shader - /// - //////////////////////////////////////////////////////////// - public Shader(Stream vertexShaderStream, Stream geometryShaderStream, Stream fragmentShaderStream) : - base(IntPtr.Zero) + //////////////////////////////////////////////////////////// + /// + /// Load the vertex, geometry and fragment shaders from custom streams + /// + /// + /// + /// This function loads the vertex, geometry and fragment + /// shaders. Pass NULL if you don't want to load + /// a specific shader. + /// The sources must be valid shaders in GLSL language. GLSL is + /// a C-like language dedicated to OpenGL shaders; you'll + /// probably need to read a good documentation for it before + /// writing your own shaders. + /// + /// Source stream to read the vertex shader from, or null to skip this shader + /// Source stream to read the geometry shader from, or null to skip this shader + /// Source stream to read the fragment shader from, or null to skip this shader + /// + //////////////////////////////////////////////////////////// + public Shader(Stream vertexShaderStream, Stream geometryShaderStream, Stream fragmentShaderStream) : + base(IntPtr.Zero) + { + // using these funky conditional operators because StreamAdaptor doesn't have some method for dealing with + // its constructor argument being null + using (StreamAdaptor vertexAdaptor = vertexShaderStream != null ? new StreamAdaptor(vertexShaderStream) : null, + geometryAdaptor = geometryShaderStream != null ? new StreamAdaptor(geometryShaderStream) : null, + fragmentAdaptor = fragmentShaderStream != null ? new StreamAdaptor(fragmentShaderStream) : null) { - // using these funky conditional operators because StreamAdaptor doesn't have some method for dealing with - // its constructor argument being null - using (StreamAdaptor vertexAdaptor = vertexShaderStream != null ? new StreamAdaptor(vertexShaderStream) : null, - geometryAdaptor = geometryShaderStream != null ? new StreamAdaptor(geometryShaderStream) : null, - fragmentAdaptor = fragmentShaderStream != null ? new StreamAdaptor(fragmentShaderStream) : null) - { - CPointer = sfShader_createFromStream(vertexAdaptor != null ? vertexAdaptor.InputStreamPtr : IntPtr.Zero, - geometryAdaptor != null ? geometryAdaptor.InputStreamPtr : IntPtr.Zero, - fragmentAdaptor != null ? fragmentAdaptor.InputStreamPtr : IntPtr.Zero); - } - - if (IsInvalid) - { - throw new LoadingFailedException("shader"); - } + CPointer = sfShader_createFromStream(vertexAdaptor?.InputStreamPtr ?? IntPtr.Zero, + geometryAdaptor?.InputStreamPtr ?? IntPtr.Zero, + fragmentAdaptor?.InputStreamPtr ?? IntPtr.Zero); } - //////////////////////////////////////////////////////////// - /// - /// Get the underlying OpenGL handle of the shader. - /// - /// - /// You shouldn't need to use this handle, unless you have - /// very specific stuff to implement that SFML doesn't support, - /// or implement a temporary workaround until a bug is fixed. - /// - //////////////////////////////////////////////////////////// - public uint NativeHandle => sfShader_getNativeHandle(CPointer); - - //////////////////////////////////////////////////////////// - /// - /// Load the vertex, geometry and fragment shaders from source code in memory - /// - /// - /// This function loads the vertex, geometry and fragment - /// shaders. Pass NULL if you don't want to load - /// a specific shader. - /// The sources must be valid shaders in GLSL language. GLSL is - /// a C-like language dedicated to OpenGL shaders; you'll - /// probably need to read a good documentation for it before - /// writing your own shaders. - /// - /// String containing the source code of the vertex shader - /// String containing the source code of the geometry shader - /// String containing the source code of the fragment shader - /// New shader instance - /// - //////////////////////////////////////////////////////////// - public static Shader FromString(string vertexShader, string geometryShader, string fragmentShader) + if (IsInvalid) { - var ptr = sfShader_createFromMemory(vertexShader, geometryShader, fragmentShader); - if (ptr == IntPtr.Zero) - { - throw new LoadingFailedException("shader"); - } - - return new Shader(ptr); + throw new LoadingFailedException("shader"); } + } + + //////////////////////////////////////////////////////////// + /// + /// Construct the shader from a pointer + /// + /// Pointer to the shader instance + //////////////////////////////////////////////////////////// + internal Shader(IntPtr ptr) : + base(ptr) + { + } + + //////////////////////////////////////////////////////////// + /// + /// Get the underlying OpenGL handle of the shader. + /// + /// + /// You shouldn't need to use this handle, unless you have + /// very specific stuff to implement that SFML doesn't support, + /// or implement a temporary workaround until a bug is fixed. + /// + //////////////////////////////////////////////////////////// + public uint NativeHandle => sfShader_getNativeHandle(CPointer); - //////////////////////////////////////////////////////////// - /// - /// Specify value for float uniform - /// - /// Name of the uniform variable in GLSL - /// Value of the float scalar - //////////////////////////////////////////////////////////// - public void SetUniform(string name, float x) => sfShader_setFloatUniform(CPointer, name, x); - - //////////////////////////////////////////////////////////// - /// - /// Specify value for vec2 uniform - /// - /// Name of the uniform variable in GLSL - /// Value of the vec2 vector - //////////////////////////////////////////////////////////// - public void SetUniform(string name, Glsl.Vec2 vector) => sfShader_setVec2Uniform(CPointer, name, vector); - - //////////////////////////////////////////////////////////// - /// - /// Specify value for vec3 uniform - /// - /// Name of the uniform variable in GLSL - /// Value of the vec3 vector - //////////////////////////////////////////////////////////// - public void SetUniform(string name, Glsl.Vec3 vector) => sfShader_setVec3Uniform(CPointer, name, vector); - - //////////////////////////////////////////////////////////// - /// - /// Specify value for vec4 uniform - /// - /// Name of the uniform variable in GLSL - /// Value of the vec4 vector - //////////////////////////////////////////////////////////// - public void SetUniform(string name, Glsl.Vec4 vector) => sfShader_setVec4Uniform(CPointer, name, vector); - - //////////////////////////////////////////////////////////// - /// - /// Specify value for int uniform - /// - /// Name of the uniform variable in GLSL - /// Value of the int scalar - //////////////////////////////////////////////////////////// - public void SetUniform(string name, int x) => sfShader_setIntUniform(CPointer, name, x); - - //////////////////////////////////////////////////////////// - /// - /// Specify value for color uniform - /// - /// Name of the uniform variable in GLSL - /// Value of the vec4 vector - //////////////////////////////////////////////////////////// - public void SetUniform(string name, Color color) => sfShader_setColorUniform(CPointer, name, color); - - //////////////////////////////////////////////////////////// - /// - /// Specify value for ivec2 uniform - /// - /// Name of the uniform variable in GLSL - /// Value of the ivec2 vector - //////////////////////////////////////////////////////////// - public void SetUniform(string name, Glsl.Ivec2 vector) => sfShader_setIvec2Uniform(CPointer, name, vector); - - //////////////////////////////////////////////////////////// - /// - /// Specify value for ivec3 uniform - /// - /// Name of the uniform variable in GLSL - /// Value of the ivec3 vector - //////////////////////////////////////////////////////////// - public void SetUniform(string name, Glsl.Ivec3 vector) => sfShader_setIvec3Uniform(CPointer, name, vector); - - //////////////////////////////////////////////////////////// - /// - /// Specify value for ivec4 uniform - /// - /// Name of the uniform variable in GLSL - /// Value of the ivec4 vector - //////////////////////////////////////////////////////////// - public void SetUniform(string name, Glsl.Ivec4 vector) => sfShader_setIvec4Uniform(CPointer, name, vector); - - //////////////////////////////////////////////////////////// - /// - /// Specify value for bool uniform - /// - /// Name of the uniform variable in GLSL - /// Value of the bool scalar - //////////////////////////////////////////////////////////// - public void SetUniform(string name, bool x) => sfShader_setBoolUniform(CPointer, name, x); - - //////////////////////////////////////////////////////////// - /// - /// Specify value for bvec2 uniform - /// - /// Name of the uniform variable in GLSL - /// Value of the bvec2 vector - //////////////////////////////////////////////////////////// - public void SetUniform(string name, Glsl.Bvec2 vector) => sfShader_setBvec2Uniform(CPointer, name, vector); - - //////////////////////////////////////////////////////////// - /// - /// Specify value for bvec3 uniform - /// - /// Name of the uniform variable in GLSL - /// Value of the bvec3 vector - //////////////////////////////////////////////////////////// - public void SetUniform(string name, Glsl.Bvec3 vector) => sfShader_setBvec3Uniform(CPointer, name, vector); - - //////////////////////////////////////////////////////////// - /// - /// Specify value for bvec4 uniform - /// - /// Name of the uniform variable in GLSL - /// Value of the bvec4 vector - //////////////////////////////////////////////////////////// - public void SetUniform(string name, Glsl.Bvec4 vector) => sfShader_setBvec4Uniform(CPointer, name, vector); - - //////////////////////////////////////////////////////////// - /// - /// Specify value for mat3 uniform - /// - /// Name of the uniform variable in GLSL - /// Value of the mat3 matrix - //////////////////////////////////////////////////////////// - public void SetUniform(string name, Glsl.Mat3 matrix) => sfShader_setMat3Uniform(CPointer, name, matrix); - - //////////////////////////////////////////////////////////// - /// - /// Specify value for mat4 uniform - /// - /// Name of the uniform variable in GLSL - /// Value of the mat4 matrix - //////////////////////////////////////////////////////////// - public void SetUniform(string name, Glsl.Mat4 matrix) => sfShader_setMat4Uniform(CPointer, name, matrix); - - //////////////////////////////////////////////////////////// - /// - /// Specify a texture as sampler2D uniform - /// - /// - /// - /// name is the name of the variable to change in the shader. - /// The corresponding parameter in the shader must be a 2D texture - /// (sampler2D GLSL type). - /// - /// Example: - /// - /// uniform sampler2D the_texture; // this is the variable in the shader - /// - /// - /// sf::Texture texture; - /// ... - /// shader.setUniform("the_texture", texture); - /// - /// It is important to note that must remain alive as long - /// as the shader uses it, no copy is made internally. - /// - /// To use the texture of the object being drawn, which cannot be - /// known in advance, you can pass the special value - /// Shader.CurrentTexture: - /// - /// shader.setUniform("the_texture", Shader.CurrentTexture); - /// - /// - /// - /// - /// Name of the texture in the shader - /// Texture to assign - /// - //////////////////////////////////////////////////////////// - public void SetUniform(string name, Texture texture) + //////////////////////////////////////////////////////////// + /// + /// Load the vertex, geometry and fragment shaders from source code in memory + /// + /// + /// This function loads the vertex, geometry and fragment + /// shaders. Pass NULL if you don't want to load + /// a specific shader. + /// The sources must be valid shaders in GLSL language. GLSL is + /// a C-like language dedicated to OpenGL shaders; you'll + /// probably need to read a good documentation for it before + /// writing your own shaders. + /// + /// String containing the source code of the vertex shader + /// String containing the source code of the geometry shader + /// String containing the source code of the fragment shader + /// New shader instance + /// + //////////////////////////////////////////////////////////// + public static Shader FromString(string vertexShader, string geometryShader, string fragmentShader) + { + var ptr = sfShader_createFromMemory(vertexShader, geometryShader, fragmentShader); + if (ptr == IntPtr.Zero) { - // Keep a reference to the Texture so it doesn't get GC'd - _textures[name] = texture; - sfShader_setTextureUniform(CPointer, name, texture.CPointer); + throw new LoadingFailedException("shader"); } - //////////////////////////////////////////////////////////// - /// - /// Specify current texture as \p sampler2D uniform - /// - /// - /// - /// This overload maps a shader texture variable to the - /// texture of the object being drawn, which cannot be - /// known in advance. The second argument must be - /// . - /// The corresponding parameter in the shader must be a 2D texture - /// (sampler2D GLSL type). - /// - /// Example: - /// - /// uniform sampler2D current; // this is the variable in the shader - /// - /// - /// shader.setUniform("current", Shader.CurrentTexture); - /// - /// - /// - /// - /// Name of the texture in the shader - /// - //////////////////////////////////////////////////////////// - public void SetUniform(string name, CurrentTextureType current) => sfShader_setCurrentTextureUniform(CPointer, name); - - //////////////////////////////////////////////////////////// - /// - /// Specify values for float[] array uniforms - /// - /// Name of the uniform variable in GLSL - /// array of float values - //////////////////////////////////////////////////////////// - public unsafe void SetUniformArray(string name, float[] array) + return new Shader(ptr); + } + + //////////////////////////////////////////////////////////// + /// + /// Specify value for float uniform + /// + /// Name of the uniform variable in GLSL + /// Value of the float scalar + //////////////////////////////////////////////////////////// + public void SetUniform(string name, float x) => sfShader_setFloatUniform(CPointer, name, x); + + //////////////////////////////////////////////////////////// + /// + /// Specify value for vec2 uniform + /// + /// Name of the uniform variable in GLSL + /// Value of the vec2 vector + //////////////////////////////////////////////////////////// + public void SetUniform(string name, Glsl.Vec2 vector) => sfShader_setVec2Uniform(CPointer, name, vector); + + //////////////////////////////////////////////////////////// + /// + /// Specify value for vec3 uniform + /// + /// Name of the uniform variable in GLSL + /// Value of the vec3 vector + //////////////////////////////////////////////////////////// + public void SetUniform(string name, Glsl.Vec3 vector) => sfShader_setVec3Uniform(CPointer, name, vector); + + //////////////////////////////////////////////////////////// + /// + /// Specify value for vec4 uniform + /// + /// Name of the uniform variable in GLSL + /// Value of the vec4 vector + //////////////////////////////////////////////////////////// + public void SetUniform(string name, Glsl.Vec4 vector) => sfShader_setVec4Uniform(CPointer, name, vector); + + //////////////////////////////////////////////////////////// + /// + /// Specify value for int uniform + /// + /// Name of the uniform variable in GLSL + /// Value of the int scalar + //////////////////////////////////////////////////////////// + public void SetUniform(string name, int x) => sfShader_setIntUniform(CPointer, name, x); + + //////////////////////////////////////////////////////////// + /// + /// Specify value for color uniform + /// + /// Name of the uniform variable in GLSL + /// Value of the vec4 vector + //////////////////////////////////////////////////////////// + public void SetUniform(string name, Color color) => sfShader_setColorUniform(CPointer, name, color); + + //////////////////////////////////////////////////////////// + /// + /// Specify value for ivec2 uniform + /// + /// Name of the uniform variable in GLSL + /// Value of the ivec2 vector + //////////////////////////////////////////////////////////// + public void SetUniform(string name, Glsl.Ivec2 vector) => sfShader_setIvec2Uniform(CPointer, name, vector); + + //////////////////////////////////////////////////////////// + /// + /// Specify value for ivec3 uniform + /// + /// Name of the uniform variable in GLSL + /// Value of the ivec3 vector + //////////////////////////////////////////////////////////// + public void SetUniform(string name, Glsl.Ivec3 vector) => sfShader_setIvec3Uniform(CPointer, name, vector); + + //////////////////////////////////////////////////////////// + /// + /// Specify value for ivec4 uniform + /// + /// Name of the uniform variable in GLSL + /// Value of the ivec4 vector + //////////////////////////////////////////////////////////// + public void SetUniform(string name, Glsl.Ivec4 vector) => sfShader_setIvec4Uniform(CPointer, name, vector); + + //////////////////////////////////////////////////////////// + /// + /// Specify value for bool uniform + /// + /// Name of the uniform variable in GLSL + /// Value of the bool scalar + //////////////////////////////////////////////////////////// + public void SetUniform(string name, bool x) => sfShader_setBoolUniform(CPointer, name, x); + + //////////////////////////////////////////////////////////// + /// + /// Specify value for bvec2 uniform + /// + /// Name of the uniform variable in GLSL + /// Value of the bvec2 vector + //////////////////////////////////////////////////////////// + public void SetUniform(string name, Glsl.Bvec2 vector) => sfShader_setBvec2Uniform(CPointer, name, vector); + + //////////////////////////////////////////////////////////// + /// + /// Specify value for bvec3 uniform + /// + /// Name of the uniform variable in GLSL + /// Value of the bvec3 vector + //////////////////////////////////////////////////////////// + public void SetUniform(string name, Glsl.Bvec3 vector) => sfShader_setBvec3Uniform(CPointer, name, vector); + + //////////////////////////////////////////////////////////// + /// + /// Specify value for bvec4 uniform + /// + /// Name of the uniform variable in GLSL + /// Value of the bvec4 vector + //////////////////////////////////////////////////////////// + public void SetUniform(string name, Glsl.Bvec4 vector) => sfShader_setBvec4Uniform(CPointer, name, vector); + + //////////////////////////////////////////////////////////// + /// + /// Specify value for mat3 uniform + /// + /// Name of the uniform variable in GLSL + /// Value of the mat3 matrix + //////////////////////////////////////////////////////////// + public void SetUniform(string name, Glsl.Mat3 matrix) => sfShader_setMat3Uniform(CPointer, name, matrix); + + //////////////////////////////////////////////////////////// + /// + /// Specify value for mat4 uniform + /// + /// Name of the uniform variable in GLSL + /// Value of the mat4 matrix + //////////////////////////////////////////////////////////// + public void SetUniform(string name, Glsl.Mat4 matrix) => sfShader_setMat4Uniform(CPointer, name, matrix); + + //////////////////////////////////////////////////////////// + /// + /// Specify a texture as sampler2D uniform + /// + /// + /// + /// name is the name of the variable to change in the shader. + /// The corresponding parameter in the shader must be a 2D texture + /// (sampler2D GLSL type). + /// + /// Example: + /// + /// uniform sampler2D the_texture; // this is the variable in the shader + /// + /// + /// sf::Texture texture; + /// ... + /// shader.setUniform("the_texture", texture); + /// + /// It is important to note that must remain alive as long + /// as the shader uses it, no copy is made internally. + /// + /// To use the texture of the object being drawn, which cannot be + /// known in advance, you can pass the special value + /// Shader.CurrentTexture: + /// + /// shader.setUniform("the_texture", Shader.CurrentTexture); + /// + /// + /// + /// + /// Name of the texture in the shader + /// Texture to assign + /// + //////////////////////////////////////////////////////////// + public void SetUniform(string name, Texture texture) + { + // Keep a reference to the Texture so it doesn't get GC'd + _textures[name] = texture; + sfShader_setTextureUniform(CPointer, name, texture.CPointer); + } + + //////////////////////////////////////////////////////////// + /// + /// Specify current texture as \p sampler2D uniform + /// + /// + /// + /// This overload maps a shader texture variable to the + /// texture of the object being drawn, which cannot be + /// known in advance. The second argument must be + /// . + /// The corresponding parameter in the shader must be a 2D texture + /// (sampler2D GLSL type). + /// + /// Example: + /// + /// uniform sampler2D current; // this is the variable in the shader + /// + /// + /// shader.setUniform("current", Shader.CurrentTexture); + /// + /// + /// + /// + /// Name of the texture in the shader + /// + //////////////////////////////////////////////////////////// + public void SetUniform(string name, CurrentTextureType current) => sfShader_setCurrentTextureUniform(CPointer, name); + + //////////////////////////////////////////////////////////// + /// + /// Specify values for float[] array uniforms + /// + /// Name of the uniform variable in GLSL + /// array of float values + //////////////////////////////////////////////////////////// + public unsafe void SetUniformArray(string name, float[] array) + { + fixed (float* data = array) { - fixed (float* data = array) - { - sfShader_setFloatUniformArray(CPointer, name, data, (UIntPtr)array.Length); - } + sfShader_setFloatUniformArray(CPointer, name, data, (UIntPtr)array.Length); } + } - //////////////////////////////////////////////////////////// - /// - /// Specify values for vec2[] array uniforms - /// - /// Name of the uniform variable in GLSL - /// array of vec2 values - //////////////////////////////////////////////////////////// - public unsafe void SetUniformArray(string name, Glsl.Vec2[] array) + //////////////////////////////////////////////////////////// + /// + /// Specify values for vec2[] array uniforms + /// + /// Name of the uniform variable in GLSL + /// array of vec2 values + //////////////////////////////////////////////////////////// + public unsafe void SetUniformArray(string name, Glsl.Vec2[] array) + { + fixed (Glsl.Vec2* data = array) { - fixed (Glsl.Vec2* data = array) - { - sfShader_setVec2UniformArray(CPointer, name, data, (UIntPtr)array.Length); - } + sfShader_setVec2UniformArray(CPointer, name, data, (UIntPtr)array.Length); } + } - //////////////////////////////////////////////////////////// - /// - /// Specify values for vec3[] array uniforms - /// - /// Name of the uniform variable in GLSL - /// array of vec3 values - //////////////////////////////////////////////////////////// - public unsafe void SetUniformArray(string name, Glsl.Vec3[] array) + //////////////////////////////////////////////////////////// + /// + /// Specify values for vec3[] array uniforms + /// + /// Name of the uniform variable in GLSL + /// array of vec3 values + //////////////////////////////////////////////////////////// + public unsafe void SetUniformArray(string name, Glsl.Vec3[] array) + { + fixed (Glsl.Vec3* data = array) { - fixed (Glsl.Vec3* data = array) - { - sfShader_setVec3UniformArray(CPointer, name, data, (UIntPtr)array.Length); - } + sfShader_setVec3UniformArray(CPointer, name, data, (UIntPtr)array.Length); } + } - //////////////////////////////////////////////////////////// - /// - /// Specify values for vec4[] array uniforms - /// - /// Name of the uniform variable in GLSL - /// array of vec4 values - //////////////////////////////////////////////////////////// - public unsafe void SetUniformArray(string name, Glsl.Vec4[] array) + //////////////////////////////////////////////////////////// + /// + /// Specify values for vec4[] array uniforms + /// + /// Name of the uniform variable in GLSL + /// array of vec4 values + //////////////////////////////////////////////////////////// + public unsafe void SetUniformArray(string name, Glsl.Vec4[] array) + { + fixed (Glsl.Vec4* data = array) { - fixed (Glsl.Vec4* data = array) - { - sfShader_setVec4UniformArray(CPointer, name, data, (UIntPtr)array.Length); - } + sfShader_setVec4UniformArray(CPointer, name, data, (UIntPtr)array.Length); } + } - //////////////////////////////////////////////////////////// - /// - /// Specify values for mat3[] array uniforms - /// - /// Name of the uniform variable in GLSL - /// array of mat3 values - //////////////////////////////////////////////////////////// - public unsafe void SetUniformArray(string name, Glsl.Mat3[] array) + //////////////////////////////////////////////////////////// + /// + /// Specify values for mat3[] array uniforms + /// + /// Name of the uniform variable in GLSL + /// array of mat3 values + //////////////////////////////////////////////////////////// + public unsafe void SetUniformArray(string name, Glsl.Mat3[] array) + { + fixed (Glsl.Mat3* data = array) { - fixed (Glsl.Mat3* data = array) - { - sfShader_setMat3UniformArray(CPointer, name, data, (UIntPtr)array.Length); - } + sfShader_setMat3UniformArray(CPointer, name, data, (UIntPtr)array.Length); } + } - //////////////////////////////////////////////////////////// - /// - /// Specify values for mat4[] array uniforms - /// - /// Name of the uniform variable in GLSL - /// array of mat4 values - //////////////////////////////////////////////////////////// - public unsafe void SetUniformArray(string name, Glsl.Mat4[] array) + //////////////////////////////////////////////////////////// + /// + /// Specify values for mat4[] array uniforms + /// + /// Name of the uniform variable in GLSL + /// array of mat4 values + //////////////////////////////////////////////////////////// + public unsafe void SetUniformArray(string name, Glsl.Mat4[] array) + { + fixed (Glsl.Mat4* data = array) { - fixed (Glsl.Mat4* data = array) - { - sfShader_setMat4UniformArray(CPointer, name, data, (UIntPtr)array.Length); - } + sfShader_setMat4UniformArray(CPointer, name, data, (UIntPtr)array.Length); } + } - //////////////////////////////////////////////////////////// - /// - /// Bind a shader for rendering - /// - /// Shader to bind (can be null to use no shader) - //////////////////////////////////////////////////////////// - public static void Bind(Shader shader) => sfShader_bind(shader != null ? shader.CPointer : IntPtr.Zero); - - //////////////////////////////////////////////////////////// - /// - /// Tell whether or not the system supports shaders. - /// - /// - /// - /// This property should always be checked before using - /// the shader features. If it returns false, then - /// any attempt to use Shader will fail. - /// - //////////////////////////////////////////////////////////// - public static bool IsAvailable => sfShader_isAvailable(); - - //////////////////////////////////////////////////////////// - /// - /// Tell whether or not the system supports geometry shaders. - /// - /// - /// - /// This property should always be checked before using - /// the geometry shader features. If it returns false, then - /// any attempt to use geometry shader features will fail. - /// - /// Note: The first call to this function, whether by your - /// code or SFML will result in a context switch. - /// - //////////////////////////////////////////////////////////// - public static bool IsGeometryAvailable => sfShader_isGeometryAvailable(); - - //////////////////////////////////////////////////////////// - /// - /// Provide a string describing the object - /// - /// String description of the object - //////////////////////////////////////////////////////////// - public override string ToString() - { - if (IsInvalid) - { - return MakeDisposedObjectString(); - } + //////////////////////////////////////////////////////////// + /// + /// Bind a shader for rendering + /// + /// Shader to bind (can be null to use no shader) + //////////////////////////////////////////////////////////// + public static void Bind(Shader shader) => sfShader_bind(shader?.CPointer ?? IntPtr.Zero); - return "[Shader]"; + //////////////////////////////////////////////////////////// + /// + /// Tell whether or not the system supports shaders. + /// + /// + /// + /// This property should always be checked before using + /// the shader features. If it returns false, then + /// any attempt to use Shader will fail. + /// + //////////////////////////////////////////////////////////// + public static bool IsAvailable => sfShader_isAvailable(); + + //////////////////////////////////////////////////////////// + /// + /// Tell whether or not the system supports geometry shaders. + /// + /// + /// + /// This property should always be checked before using + /// the geometry shader features. If it returns false, then + /// any attempt to use geometry shader features will fail. + /// + /// Note: The first call to this function, whether by your + /// code or SFML will result in a context switch. + /// + //////////////////////////////////////////////////////////// + public static bool IsGeometryAvailable => sfShader_isGeometryAvailable(); + + //////////////////////////////////////////////////////////// + /// + /// Provide a string describing the object + /// + /// String description of the object + //////////////////////////////////////////////////////////// + public override string ToString() + { + if (IsInvalid) + { + return MakeDisposedObjectString(); } - //////////////////////////////////////////////////////////// - /// - /// Handle the destruction of the object - /// - /// Is the GC disposing the object, or is it an explicit call ? - //////////////////////////////////////////////////////////// - protected override void Destroy(bool disposing) + return "[Shader]"; + } + + //////////////////////////////////////////////////////////// + /// + /// Handle the destruction of the object + /// + /// Is the GC disposing the object, or is it an explicit call ? + //////////////////////////////////////////////////////////// + protected override void Destroy(bool disposing) + { + if (!disposing) { - if (!disposing) - { - _ = Context.Global.SetActive(true); - } - - _textures.Clear(); - sfShader_destroy(CPointer); - - if (!disposing) - { - _ = Context.Global.SetActive(false); - } + _ = Context.Global.SetActive(true); } - //////////////////////////////////////////////////////////// - /// - /// Construct the shader from a pointer - /// - /// Pointer to the shader instance - //////////////////////////////////////////////////////////// - public Shader(IntPtr ptr) : - base(ptr) + _textures.Clear(); + sfShader_destroy(CPointer); + + if (!disposing) { + _ = Context.Global.SetActive(false); } + } - // Keeps references to used Textures for GC prevention during use - private readonly Dictionary _textures = new Dictionary(); + // Keeps references to used Textures for GC prevention during use + private readonly Dictionary _textures = []; - #region Imports - [DllImport(CSFML.Graphics, CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] - private static extern IntPtr sfShader_createFromFile(string vertexShaderFilename, string geometryShaderFilename, string fragmentShaderFilename); + #region Imports + [DllImport(CSFML.Graphics, CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] + private static extern IntPtr sfShader_createFromFile(string vertexShaderFilename, string geometryShaderFilename, string fragmentShaderFilename); - [DllImport(CSFML.Graphics, CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] - private static extern IntPtr sfShader_createFromMemory(string vertexShader, string geometryShader, string fragmentShader); + [DllImport(CSFML.Graphics, CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] + private static extern IntPtr sfShader_createFromMemory(string vertexShader, string geometryShader, string fragmentShader); - [DllImport(CSFML.Graphics, CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] - private static extern IntPtr sfShader_createFromStream(IntPtr vertexShaderStream, IntPtr geometryShaderStream, IntPtr fragmentShaderStream); + [DllImport(CSFML.Graphics, CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] + private static extern IntPtr sfShader_createFromStream(IntPtr vertexShaderStream, IntPtr geometryShaderStream, IntPtr fragmentShaderStream); - [DllImport(CSFML.Graphics, CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] - private static extern void sfShader_destroy(IntPtr shader); + [DllImport(CSFML.Graphics, CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] + private static extern void sfShader_destroy(IntPtr shader); - [DllImport(CSFML.Graphics, CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] - private static extern void sfShader_setFloatUniform(IntPtr shader, string name, float x); + [DllImport(CSFML.Graphics, CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] + private static extern void sfShader_setFloatUniform(IntPtr shader, string name, float x); - [DllImport(CSFML.Graphics, CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] - private static extern void sfShader_setVec2Uniform(IntPtr shader, string name, Glsl.Vec2 vector); + [DllImport(CSFML.Graphics, CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] + private static extern void sfShader_setVec2Uniform(IntPtr shader, string name, Glsl.Vec2 vector); - [DllImport(CSFML.Graphics, CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] - private static extern void sfShader_setVec3Uniform(IntPtr shader, string name, Glsl.Vec3 vector); + [DllImport(CSFML.Graphics, CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] + private static extern void sfShader_setVec3Uniform(IntPtr shader, string name, Glsl.Vec3 vector); - [DllImport(CSFML.Graphics, CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] - private static extern void sfShader_setVec4Uniform(IntPtr shader, string name, Glsl.Vec4 vector); + [DllImport(CSFML.Graphics, CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] + private static extern void sfShader_setVec4Uniform(IntPtr shader, string name, Glsl.Vec4 vector); - [DllImport(CSFML.Graphics, CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] - private static extern void sfShader_setIntUniform(IntPtr shader, string name, int x); + [DllImport(CSFML.Graphics, CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] + private static extern void sfShader_setIntUniform(IntPtr shader, string name, int x); - [DllImport(CSFML.Graphics, CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] - private static extern void sfShader_setColorUniform(IntPtr shader, string name, Color color); + [DllImport(CSFML.Graphics, CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] + private static extern void sfShader_setColorUniform(IntPtr shader, string name, Color color); - [DllImport(CSFML.Graphics, CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] - private static extern void sfShader_setIvec2Uniform(IntPtr shader, string name, Glsl.Ivec2 vector); + [DllImport(CSFML.Graphics, CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] + private static extern void sfShader_setIvec2Uniform(IntPtr shader, string name, Glsl.Ivec2 vector); - [DllImport(CSFML.Graphics, CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] - private static extern void sfShader_setIvec3Uniform(IntPtr shader, string name, Glsl.Ivec3 vector); + [DllImport(CSFML.Graphics, CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] + private static extern void sfShader_setIvec3Uniform(IntPtr shader, string name, Glsl.Ivec3 vector); - [DllImport(CSFML.Graphics, CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] - private static extern void sfShader_setIvec4Uniform(IntPtr shader, string name, Glsl.Ivec4 vector); + [DllImport(CSFML.Graphics, CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] + private static extern void sfShader_setIvec4Uniform(IntPtr shader, string name, Glsl.Ivec4 vector); - [DllImport(CSFML.Graphics, CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] - private static extern void sfShader_setBoolUniform(IntPtr shader, string name, bool x); + [DllImport(CSFML.Graphics, CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] + private static extern void sfShader_setBoolUniform(IntPtr shader, string name, bool x); - [DllImport(CSFML.Graphics, CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] - private static extern void sfShader_setBvec2Uniform(IntPtr shader, string name, Glsl.Bvec2 vector); + [DllImport(CSFML.Graphics, CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] + private static extern void sfShader_setBvec2Uniform(IntPtr shader, string name, Glsl.Bvec2 vector); - [DllImport(CSFML.Graphics, CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] - private static extern void sfShader_setBvec3Uniform(IntPtr shader, string name, Glsl.Bvec3 vector); + [DllImport(CSFML.Graphics, CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] + private static extern void sfShader_setBvec3Uniform(IntPtr shader, string name, Glsl.Bvec3 vector); - [DllImport(CSFML.Graphics, CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] - private static extern void sfShader_setBvec4Uniform(IntPtr shader, string name, Glsl.Bvec4 vector); + [DllImport(CSFML.Graphics, CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] + private static extern void sfShader_setBvec4Uniform(IntPtr shader, string name, Glsl.Bvec4 vector); - [DllImport(CSFML.Graphics, CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] - private static extern void sfShader_setMat3Uniform(IntPtr shader, string name, Glsl.Mat3 matrix); + [DllImport(CSFML.Graphics, CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] + private static extern void sfShader_setMat3Uniform(IntPtr shader, string name, Glsl.Mat3 matrix); - [DllImport(CSFML.Graphics, CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] - private static extern void sfShader_setMat4Uniform(IntPtr shader, string name, Glsl.Mat4 matrix); + [DllImport(CSFML.Graphics, CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] + private static extern void sfShader_setMat4Uniform(IntPtr shader, string name, Glsl.Mat4 matrix); - [DllImport(CSFML.Graphics, CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] - private static extern void sfShader_setTextureUniform(IntPtr shader, string name, IntPtr texture); + [DllImport(CSFML.Graphics, CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] + private static extern void sfShader_setTextureUniform(IntPtr shader, string name, IntPtr texture); - [DllImport(CSFML.Graphics, CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] - private static extern void sfShader_setCurrentTextureUniform(IntPtr shader, string name); + [DllImport(CSFML.Graphics, CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] + private static extern void sfShader_setCurrentTextureUniform(IntPtr shader, string name); - [DllImport(CSFML.Graphics, CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] - private static extern unsafe void sfShader_setFloatUniformArray(IntPtr shader, string name, float* data, UIntPtr length); + [DllImport(CSFML.Graphics, CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] + private static extern unsafe void sfShader_setFloatUniformArray(IntPtr shader, string name, float* data, UIntPtr length); - [DllImport(CSFML.Graphics, CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] - private static extern unsafe void sfShader_setVec2UniformArray(IntPtr shader, string name, Glsl.Vec2* data, UIntPtr length); + [DllImport(CSFML.Graphics, CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] + private static extern unsafe void sfShader_setVec2UniformArray(IntPtr shader, string name, Glsl.Vec2* data, UIntPtr length); - [DllImport(CSFML.Graphics, CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] - private static extern unsafe void sfShader_setVec3UniformArray(IntPtr shader, string name, Glsl.Vec3* data, UIntPtr length); + [DllImport(CSFML.Graphics, CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] + private static extern unsafe void sfShader_setVec3UniformArray(IntPtr shader, string name, Glsl.Vec3* data, UIntPtr length); - [DllImport(CSFML.Graphics, CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] - private static extern unsafe void sfShader_setVec4UniformArray(IntPtr shader, string name, Glsl.Vec4* data, UIntPtr length); + [DllImport(CSFML.Graphics, CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] + private static extern unsafe void sfShader_setVec4UniformArray(IntPtr shader, string name, Glsl.Vec4* data, UIntPtr length); - [DllImport(CSFML.Graphics, CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] - private static extern unsafe void sfShader_setMat3UniformArray(IntPtr shader, string name, Glsl.Mat3* data, UIntPtr length); + [DllImport(CSFML.Graphics, CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] + private static extern unsafe void sfShader_setMat3UniformArray(IntPtr shader, string name, Glsl.Mat3* data, UIntPtr length); - [DllImport(CSFML.Graphics, CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] - private static extern unsafe void sfShader_setMat4UniformArray(IntPtr shader, string name, Glsl.Mat4* data, UIntPtr length); + [DllImport(CSFML.Graphics, CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] + private static extern unsafe void sfShader_setMat4UniformArray(IntPtr shader, string name, Glsl.Mat4* data, UIntPtr length); - [DllImport(CSFML.Graphics, CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] - private static extern uint sfShader_getNativeHandle(IntPtr shader); + [DllImport(CSFML.Graphics, CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] + private static extern uint sfShader_getNativeHandle(IntPtr shader); - [DllImport(CSFML.Graphics, CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] - private static extern void sfShader_bind(IntPtr shader); + [DllImport(CSFML.Graphics, CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] + private static extern void sfShader_bind(IntPtr shader); - [DllImport(CSFML.Graphics, CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] - [return: MarshalAs(UnmanagedType.I1)] - private static extern bool sfShader_isAvailable(); + [DllImport(CSFML.Graphics, CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] + [return: MarshalAs(UnmanagedType.I1)] + private static extern bool sfShader_isAvailable(); - [DllImport(CSFML.Graphics, CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] - [return: MarshalAs(UnmanagedType.I1)] - private static extern bool sfShader_isGeometryAvailable(); - #endregion - } + [DllImport(CSFML.Graphics, CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] + [return: MarshalAs(UnmanagedType.I1)] + private static extern bool sfShader_isGeometryAvailable(); + #endregion } diff --git a/src/SFML.Graphics/Shape.cs b/src/SFML.Graphics/Shape.cs index 5558aba6..281c9030 100644 --- a/src/SFML.Graphics/Shape.cs +++ b/src/SFML.Graphics/Shape.cs @@ -3,288 +3,287 @@ using System.Security; using SFML.System; -namespace SFML.Graphics +namespace SFML.Graphics; + +//////////////////////////////////////////////////////////// +/// +/// Base class for textured shapes with outline +/// +//////////////////////////////////////////////////////////// +public abstract class Shape : Transformable, IDrawable { //////////////////////////////////////////////////////////// /// - /// Base class for textured shapes with outline + /// Source texture of the shape /// //////////////////////////////////////////////////////////// - public abstract class Shape : Transformable, IDrawable + public Texture Texture { - //////////////////////////////////////////////////////////// - /// - /// Source texture of the shape - /// - //////////////////////////////////////////////////////////// - public Texture Texture - { - get => _texture; - set { _texture = value; sfShape_setTexture(CPointer, value != null ? value.CPointer : IntPtr.Zero, false); } - } + get => _texture; + set { _texture = value; sfShape_setTexture(CPointer, value?.CPointer ?? IntPtr.Zero, false); } + } - //////////////////////////////////////////////////////////// - /// - /// Sub-rectangle of the texture that the shape will display - /// - //////////////////////////////////////////////////////////// - public IntRect TextureRect - { - get => sfShape_getTextureRect(CPointer); - set => sfShape_setTextureRect(CPointer, value); - } + //////////////////////////////////////////////////////////// + /// + /// Sub-rectangle of the texture that the shape will display + /// + //////////////////////////////////////////////////////////// + public IntRect TextureRect + { + get => sfShape_getTextureRect(CPointer); + set => sfShape_setTextureRect(CPointer, value); + } - //////////////////////////////////////////////////////////// - /// - /// Fill color of the shape - /// - //////////////////////////////////////////////////////////// - public Color FillColor - { - get => sfShape_getFillColor(CPointer); - set => sfShape_setFillColor(CPointer, value); - } + //////////////////////////////////////////////////////////// + /// + /// Fill color of the shape + /// + //////////////////////////////////////////////////////////// + public Color FillColor + { + get => sfShape_getFillColor(CPointer); + set => sfShape_setFillColor(CPointer, value); + } - //////////////////////////////////////////////////////////// - /// - /// Outline color of the shape - /// - //////////////////////////////////////////////////////////// - public Color OutlineColor - { - get => sfShape_getOutlineColor(CPointer); - set => sfShape_setOutlineColor(CPointer, value); - } + //////////////////////////////////////////////////////////// + /// + /// Outline color of the shape + /// + //////////////////////////////////////////////////////////// + public Color OutlineColor + { + get => sfShape_getOutlineColor(CPointer); + set => sfShape_setOutlineColor(CPointer, value); + } - //////////////////////////////////////////////////////////// - /// - /// Thickness of the shape's outline - /// - //////////////////////////////////////////////////////////// - public float OutlineThickness - { - get => sfShape_getOutlineThickness(CPointer); - set => sfShape_setOutlineThickness(CPointer, value); - } + //////////////////////////////////////////////////////////// + /// + /// Thickness of the shape's outline + /// + //////////////////////////////////////////////////////////// + public float OutlineThickness + { + get => sfShape_getOutlineThickness(CPointer); + set => sfShape_setOutlineThickness(CPointer, value); + } - //////////////////////////////////////////////////////////// - /// - /// Get the total number of points of the shape - /// - /// The total point count - //////////////////////////////////////////////////////////// - public abstract uint GetPointCount(); - - //////////////////////////////////////////////////////////// - /// - /// 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. - /// - /// Index of the point to get, in range [0 .. PointCount - 1] - /// index-th point of the shape - //////////////////////////////////////////////////////////// - public abstract Vector2f GetPoint(uint index); - - //////////////////////////////////////////////////////////// - /// - /// 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. - /// - /// - /// The geometric center of the shape - //////////////////////////////////////////////////////////// - public virtual Vector2f GetGeometricCenter() => sfShape_getGeometricCenter(CPointer); - - //////////////////////////////////////////////////////////// - /// - /// 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. - /// - /// Local bounding rectangle of the entity - //////////////////////////////////////////////////////////// - public FloatRect GetLocalBounds() => sfShape_getLocalBounds(CPointer); - - //////////////////////////////////////////////////////////// - /// - /// Get the global bounding rectangle of the entity. - /// - /// The returned rectangle is in global coordinates, which means - /// that it takes in account the transformations (translation, - /// rotation, scale, ...) that are applied to the entity. - /// In other words, this function returns the bounds of the - /// sprite in the global 2D world's coordinate system. - /// - /// Global bounding rectangle of the entity - //////////////////////////////////////////////////////////// - public FloatRect GetGlobalBounds() => - // we don't use the native getGlobalBounds function, - // because we override the object's transform - Transform.TransformRect(GetLocalBounds()); - - //////////////////////////////////////////////////////////// - /// - /// Draw the shape to a render target - /// - /// Render target to draw to - /// Current render states - //////////////////////////////////////////////////////////// - public void Draw(IRenderTarget target, RenderStates states) - { - states.Transform *= Transform; - var marshaledStates = states.Marshal(); - - if (target is RenderWindow window) - { - sfRenderWindow_drawShape(window.CPointer, CPointer, ref marshaledStates); - } - else if (target is RenderTexture texture) - { - sfRenderTexture_drawShape(texture.CPointer, CPointer, ref marshaledStates); - } - } + //////////////////////////////////////////////////////////// + /// + /// Get the total number of points of the shape + /// + /// The total point count + //////////////////////////////////////////////////////////// + public abstract uint GetPointCount(); + + //////////////////////////////////////////////////////////// + /// + /// 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. + /// + /// Index of the point to get, in range [0 .. PointCount - 1] + /// index-th point of the shape + //////////////////////////////////////////////////////////// + public abstract Vector2f GetPoint(uint index); + + //////////////////////////////////////////////////////////// + /// + /// 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. + /// + /// + /// The geometric center of the shape + //////////////////////////////////////////////////////////// + public virtual Vector2f GetGeometricCenter() => sfShape_getGeometricCenter(CPointer); - //////////////////////////////////////////////////////////// - /// - /// Default constructor - /// - //////////////////////////////////////////////////////////// - protected Shape() : - base(IntPtr.Zero) + //////////////////////////////////////////////////////////// + /// + /// 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. + /// + /// Local bounding rectangle of the entity + //////////////////////////////////////////////////////////// + public FloatRect GetLocalBounds() => sfShape_getLocalBounds(CPointer); + + //////////////////////////////////////////////////////////// + /// + /// Get the global bounding rectangle of the entity. + /// + /// The returned rectangle is in global coordinates, which means + /// that it takes in account the transformations (translation, + /// rotation, scale, ...) that are applied to the entity. + /// In other words, this function returns the bounds of the + /// sprite in the global 2D world's coordinate system. + /// + /// Global bounding rectangle of the entity + //////////////////////////////////////////////////////////// + public FloatRect GetGlobalBounds() => + // we don't use the native getGlobalBounds function, + // because we override the object's transform + Transform.TransformRect(GetLocalBounds()); + + //////////////////////////////////////////////////////////// + /// + /// Draw the shape to a render target + /// + /// Render target to draw to + /// Current render states + //////////////////////////////////////////////////////////// + public void Draw(IRenderTarget target, RenderStates states) + { + states.Transform *= Transform; + var marshaledStates = states.Marshal(); + + if (target is RenderWindow window) { - _getPointCountCallback = new GetPointCountCallbackType(InternalGetPointCount); - _getPointCallback = new GetPointCallbackType(InternalGetPoint); - CPointer = sfShape_create(_getPointCountCallback, _getPointCallback, IntPtr.Zero); + sfRenderWindow_drawShape(window.CPointer, CPointer, ref marshaledStates); } - - //////////////////////////////////////////////////////////// - /// - /// Construct the shape from another shape - /// - /// Shape to copy - //////////////////////////////////////////////////////////// - public Shape(Shape copy) : - base(IntPtr.Zero) + else if (target is RenderTexture texture) { - _getPointCountCallback = new GetPointCountCallbackType(InternalGetPointCount); - _getPointCallback = new GetPointCallbackType(InternalGetPoint); - CPointer = sfShape_create(_getPointCountCallback, _getPointCallback, IntPtr.Zero); - - Origin = copy.Origin; - Position = copy.Position; - Rotation = copy.Rotation; - Scale = copy.Scale; - - Texture = copy.Texture; - TextureRect = copy.TextureRect; - FillColor = copy.FillColor; - OutlineColor = copy.OutlineColor; - OutlineThickness = copy.OutlineThickness; + sfRenderTexture_drawShape(texture.CPointer, CPointer, ref marshaledStates); } + } + + //////////////////////////////////////////////////////////// + /// + /// Default constructor + /// + //////////////////////////////////////////////////////////// + protected Shape() : + base(IntPtr.Zero) + { + _getPointCountCallback = new GetPointCountCallbackType(InternalGetPointCount); + _getPointCallback = new GetPointCallbackType(InternalGetPoint); + CPointer = sfShape_create(_getPointCountCallback, _getPointCallback, IntPtr.Zero); + } - //////////////////////////////////////////////////////////// - /// - /// Recompute the internal geometry of the shape. - /// - /// This function must be called by the derived class every time - /// the shape's points change (ie. the result of either - /// PointCount or GetPoint is different). - /// - //////////////////////////////////////////////////////////// - protected void Update() => sfShape_update(CPointer); + //////////////////////////////////////////////////////////// + /// + /// Construct the shape from another shape + /// + /// Shape to copy + //////////////////////////////////////////////////////////// + public Shape(Shape copy) : + base(IntPtr.Zero) + { + _getPointCountCallback = new GetPointCountCallbackType(InternalGetPointCount); + _getPointCallback = new GetPointCallbackType(InternalGetPoint); + CPointer = sfShape_create(_getPointCountCallback, _getPointCallback, IntPtr.Zero); + + Origin = copy.Origin; + Position = copy.Position; + Rotation = copy.Rotation; + Scale = copy.Scale; + + Texture = copy.Texture; + TextureRect = copy.TextureRect; + FillColor = copy.FillColor; + OutlineColor = copy.OutlineColor; + OutlineThickness = copy.OutlineThickness; + } - //////////////////////////////////////////////////////////// - /// - /// Handle the destruction of the object - /// - /// Is the GC disposing the object, or is it an explicit call ? - //////////////////////////////////////////////////////////// - protected override void Destroy(bool disposing) => sfShape_destroy(CPointer); + //////////////////////////////////////////////////////////// + /// + /// Recompute the internal geometry of the shape. + /// + /// This function must be called by the derived class every time + /// the shape's points change (ie. the result of either + /// PointCount or GetPoint is different). + /// + //////////////////////////////////////////////////////////// + protected void Update() => sfShape_update(CPointer); - //////////////////////////////////////////////////////////// - /// - /// Callback passed to the C API - /// - //////////////////////////////////////////////////////////// - private UIntPtr InternalGetPointCount(IntPtr userData) => (UIntPtr)GetPointCount(); + //////////////////////////////////////////////////////////// + /// + /// Handle the destruction of the object + /// + /// Is the GC disposing the object, or is it an explicit call ? + //////////////////////////////////////////////////////////// + protected override void Destroy(bool disposing) => sfShape_destroy(CPointer); + + //////////////////////////////////////////////////////////// + /// + /// Callback passed to the C API + /// + //////////////////////////////////////////////////////////// + private UIntPtr InternalGetPointCount(IntPtr userData) => (UIntPtr)GetPointCount(); - //////////////////////////////////////////////////////////// - /// - /// Callback passed to the C API - /// - //////////////////////////////////////////////////////////// - private Vector2f InternalGetPoint(UIntPtr index, IntPtr userData) => GetPoint((uint)index); + //////////////////////////////////////////////////////////// + /// + /// Callback passed to the C API + /// + //////////////////////////////////////////////////////////// + private Vector2f InternalGetPoint(UIntPtr index, IntPtr userData) => GetPoint((uint)index); - [UnmanagedFunctionPointer(CallingConvention.Cdecl)] - private delegate UIntPtr GetPointCountCallbackType(IntPtr userData); + [UnmanagedFunctionPointer(CallingConvention.Cdecl)] + private delegate UIntPtr GetPointCountCallbackType(IntPtr userData); - [UnmanagedFunctionPointer(CallingConvention.Cdecl)] - private delegate Vector2f GetPointCallbackType(UIntPtr index, IntPtr userData); + [UnmanagedFunctionPointer(CallingConvention.Cdecl)] + private delegate Vector2f GetPointCallbackType(UIntPtr index, IntPtr userData); - private readonly GetPointCountCallbackType _getPointCountCallback; - private readonly GetPointCallbackType _getPointCallback; + private readonly GetPointCountCallbackType _getPointCountCallback; + private readonly GetPointCallbackType _getPointCallback; - private Texture _texture; + private Texture _texture; - #region Imports - [DllImport(CSFML.Graphics, CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] - private static extern IntPtr sfShape_create(GetPointCountCallbackType getPointCount, GetPointCallbackType getPoint, IntPtr userData); + #region Imports + [DllImport(CSFML.Graphics, CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] + private static extern IntPtr sfShape_create(GetPointCountCallbackType getPointCount, GetPointCallbackType getPoint, IntPtr userData); - [DllImport(CSFML.Graphics, CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] - private static extern void sfShape_destroy(IntPtr cPointer); + [DllImport(CSFML.Graphics, CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] + private static extern void sfShape_destroy(IntPtr cPointer); - [DllImport(CSFML.Graphics, CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] - private static extern void sfShape_setTexture(IntPtr cPointer, IntPtr texture, bool adjustToNewSize); + [DllImport(CSFML.Graphics, CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] + private static extern void sfShape_setTexture(IntPtr cPointer, IntPtr texture, bool adjustToNewSize); - [DllImport(CSFML.Graphics, CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] - private static extern void sfShape_setTextureRect(IntPtr cPointer, IntRect rect); + [DllImport(CSFML.Graphics, CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] + private static extern void sfShape_setTextureRect(IntPtr cPointer, IntRect rect); - [DllImport(CSFML.Graphics, CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] - private static extern IntRect sfShape_getTextureRect(IntPtr cPointer); + [DllImport(CSFML.Graphics, CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] + private static extern IntRect sfShape_getTextureRect(IntPtr cPointer); - [DllImport(CSFML.Graphics, CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] - private static extern void sfShape_setFillColor(IntPtr cPointer, Color color); + [DllImport(CSFML.Graphics, CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] + private static extern void sfShape_setFillColor(IntPtr cPointer, Color color); - [DllImport(CSFML.Graphics, CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] - private static extern Color sfShape_getFillColor(IntPtr cPointer); + [DllImport(CSFML.Graphics, CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] + private static extern Color sfShape_getFillColor(IntPtr cPointer); - [DllImport(CSFML.Graphics, CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] - private static extern void sfShape_setOutlineColor(IntPtr cPointer, Color color); + [DllImport(CSFML.Graphics, CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] + private static extern void sfShape_setOutlineColor(IntPtr cPointer, Color color); - [DllImport(CSFML.Graphics, CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] - private static extern Color sfShape_getOutlineColor(IntPtr cPointer); + [DllImport(CSFML.Graphics, CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] + private static extern Color sfShape_getOutlineColor(IntPtr cPointer); - [DllImport(CSFML.Graphics, CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] - private static extern void sfShape_setOutlineThickness(IntPtr cPointer, float thickness); + [DllImport(CSFML.Graphics, CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] + private static extern void sfShape_setOutlineThickness(IntPtr cPointer, float thickness); - [DllImport(CSFML.Graphics, CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] - private static extern float sfShape_getOutlineThickness(IntPtr cPointer); + [DllImport(CSFML.Graphics, CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] + private static extern float sfShape_getOutlineThickness(IntPtr cPointer); - [DllImport(CSFML.Graphics, CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] - private static extern Vector2f sfShape_getGeometricCenter(IntPtr cPointer); + [DllImport(CSFML.Graphics, CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] + private static extern Vector2f sfShape_getGeometricCenter(IntPtr cPointer); - [DllImport(CSFML.Graphics, CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] - private static extern FloatRect sfShape_getLocalBounds(IntPtr cPointer); + [DllImport(CSFML.Graphics, CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] + private static extern FloatRect sfShape_getLocalBounds(IntPtr cPointer); - [DllImport(CSFML.Graphics, CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] - private static extern void sfShape_update(IntPtr cPointer); + [DllImport(CSFML.Graphics, CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] + private static extern void sfShape_update(IntPtr cPointer); - [DllImport(CSFML.Graphics, CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] - private static extern void sfRenderWindow_drawShape(IntPtr cPointer, IntPtr shape, ref RenderStates.MarshalData states); + [DllImport(CSFML.Graphics, CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] + private static extern void sfRenderWindow_drawShape(IntPtr cPointer, IntPtr shape, ref RenderStates.MarshalData states); - [DllImport(CSFML.Graphics, CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] - private static extern void sfRenderTexture_drawShape(IntPtr cPointer, IntPtr shape, ref RenderStates.MarshalData states); - #endregion - } + [DllImport(CSFML.Graphics, CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] + private static extern void sfRenderTexture_drawShape(IntPtr cPointer, IntPtr shape, ref RenderStates.MarshalData states); + #endregion } diff --git a/src/SFML.Graphics/Sprite.cs b/src/SFML.Graphics/Sprite.cs index a64c4383..0da19da8 100644 --- a/src/SFML.Graphics/Sprite.cs +++ b/src/SFML.Graphics/Sprite.cs @@ -3,204 +3,203 @@ using System.Security; using SFML.System; -namespace SFML.Graphics +namespace SFML.Graphics; + +//////////////////////////////////////////////////////////// +/// +/// This class defines a sprite : texture, transformations, +/// color, and draw on screen +/// +/// +/// See also the note on coordinates and undistorted rendering in SFML.Graphics.Transformable. +/// +//////////////////////////////////////////////////////////// +public class Sprite : Transformable, IDrawable { //////////////////////////////////////////////////////////// /// - /// This class defines a sprite : texture, transformations, - /// color, and draw on screen + /// Construct the sprite from a source texture /// - /// - /// See also the note on coordinates and undistorted rendering in SFML.Graphics.Transformable. - /// + /// Source texture to assign to the sprite //////////////////////////////////////////////////////////// - public class Sprite : Transformable, IDrawable + public Sprite(Texture texture) : + base(sfSprite_create(texture.CPointer)) => Texture = texture; + + //////////////////////////////////////////////////////////// + /// + /// Construct the sprite from a source texture + /// + /// Source texture to assign to the sprite + /// Sub-rectangle of the texture to assign to the sprite + //////////////////////////////////////////////////////////// + public Sprite(Texture texture, IntRect rectangle) : + base(sfSprite_create(texture.CPointer)) { - //////////////////////////////////////////////////////////// - /// - /// Construct the sprite from a source texture - /// - /// Source texture to assign to the sprite - //////////////////////////////////////////////////////////// - public Sprite(Texture texture) : - base(sfSprite_create(texture.CPointer)) => Texture = texture; - - //////////////////////////////////////////////////////////// - /// - /// Construct the sprite from a source texture - /// - /// Source texture to assign to the sprite - /// Sub-rectangle of the texture to assign to the sprite - //////////////////////////////////////////////////////////// - public Sprite(Texture texture, IntRect rectangle) : - base(sfSprite_create(texture.CPointer)) - { - Texture = texture; - TextureRect = rectangle; - } + Texture = texture; + TextureRect = rectangle; + } - //////////////////////////////////////////////////////////// - /// - /// Construct the sprite from another sprite - /// - /// Sprite to copy - //////////////////////////////////////////////////////////// - public Sprite(Sprite copy) : - base(sfSprite_copy(copy.CPointer)) - { - Origin = copy.Origin; - Position = copy.Position; - Rotation = copy.Rotation; - Scale = copy.Scale; - Texture = copy.Texture; - } + //////////////////////////////////////////////////////////// + /// + /// Construct the sprite from another sprite + /// + /// Sprite to copy + //////////////////////////////////////////////////////////// + public Sprite(Sprite copy) : + base(sfSprite_copy(copy.CPointer)) + { + Origin = copy.Origin; + Position = copy.Position; + Rotation = copy.Rotation; + Scale = copy.Scale; + Texture = copy.Texture; + } - //////////////////////////////////////////////////////////// - /// - /// Global color of the object - /// - //////////////////////////////////////////////////////////// - public Color Color - { - get => sfSprite_getColor(CPointer); - set => sfSprite_setColor(CPointer, value); - } + //////////////////////////////////////////////////////////// + /// + /// Global color of the object + /// + //////////////////////////////////////////////////////////// + public Color Color + { + get => sfSprite_getColor(CPointer); + set => sfSprite_setColor(CPointer, value); + } - //////////////////////////////////////////////////////////// - /// - /// Source texture displayed by the sprite - /// - //////////////////////////////////////////////////////////// - public Texture Texture - { - get => _texture; - set { _texture = value; sfSprite_setTexture(CPointer, value != null ? value.CPointer : IntPtr.Zero, false); } - } + //////////////////////////////////////////////////////////// + /// + /// Source texture displayed by the sprite + /// + //////////////////////////////////////////////////////////// + public Texture Texture + { + get => _texture; + set { _texture = value; sfSprite_setTexture(CPointer, value?.CPointer ?? IntPtr.Zero, false); } + } + + //////////////////////////////////////////////////////////// + /// + /// Sub-rectangle of the source image displayed by the sprite + /// + //////////////////////////////////////////////////////////// + public IntRect TextureRect + { + get => sfSprite_getTextureRect(CPointer); + set => sfSprite_setTextureRect(CPointer, value); + } + + //////////////////////////////////////////////////////////// + /// + /// 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. + /// + /// Local bounding rectangle of the entity + //////////////////////////////////////////////////////////// + public FloatRect GetLocalBounds() => sfSprite_getLocalBounds(CPointer); - //////////////////////////////////////////////////////////// - /// - /// Sub-rectangle of the source image displayed by the sprite - /// - //////////////////////////////////////////////////////////// - public IntRect TextureRect + //////////////////////////////////////////////////////////// + /// + /// Get the global bounding rectangle of the entity. + /// + /// The returned rectangle is in global coordinates, which means + /// that it takes in account the transformations (translation, + /// rotation, scale, ...) that are applied to the entity. + /// In other words, this function returns the bounds of the + /// sprite in the global 2D world's coordinate system. + /// + /// Global bounding rectangle of the entity + //////////////////////////////////////////////////////////// + public FloatRect GetGlobalBounds() => + // we don't use the native getGlobalBounds function, + // because we override the object's transform + Transform.TransformRect(GetLocalBounds()); + + //////////////////////////////////////////////////////////// + /// + /// Provide a string describing the object + /// + /// String description of the object + //////////////////////////////////////////////////////////// + public override string ToString() + { + if (IsInvalid) { - get => sfSprite_getTextureRect(CPointer); - set => sfSprite_setTextureRect(CPointer, value); + return MakeDisposedObjectString(); } - //////////////////////////////////////////////////////////// - /// - /// 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. - /// - /// Local bounding rectangle of the entity - //////////////////////////////////////////////////////////// - public FloatRect GetLocalBounds() => sfSprite_getLocalBounds(CPointer); - - //////////////////////////////////////////////////////////// - /// - /// Get the global bounding rectangle of the entity. - /// - /// The returned rectangle is in global coordinates, which means - /// that it takes in account the transformations (translation, - /// rotation, scale, ...) that are applied to the entity. - /// In other words, this function returns the bounds of the - /// sprite in the global 2D world's coordinate system. - /// - /// Global bounding rectangle of the entity - //////////////////////////////////////////////////////////// - public FloatRect GetGlobalBounds() => - // we don't use the native getGlobalBounds function, - // because we override the object's transform - Transform.TransformRect(GetLocalBounds()); - - //////////////////////////////////////////////////////////// - /// - /// Provide a string describing the object - /// - /// String description of the object - //////////////////////////////////////////////////////////// - public override string ToString() - { - if (IsInvalid) - { - return MakeDisposedObjectString(); - } + return $"[Sprite] Color({Color}) Texture({Texture}) TextureRect({TextureRect})"; + } - return $"[Sprite] Color({Color}) Texture({Texture}) TextureRect({TextureRect})"; - } + //////////////////////////////////////////////////////////// + /// + /// Draw the sprite to a render target + /// + /// Render target to draw to + /// Current render states + //////////////////////////////////////////////////////////// + public void Draw(IRenderTarget target, RenderStates states) + { + states.Transform *= Transform; + var marshaledStates = states.Marshal(); - //////////////////////////////////////////////////////////// - /// - /// Draw the sprite to a render target - /// - /// Render target to draw to - /// Current render states - //////////////////////////////////////////////////////////// - public void Draw(IRenderTarget target, RenderStates states) + if (target is RenderWindow window) { - states.Transform *= Transform; - var marshaledStates = states.Marshal(); - - if (target is RenderWindow window) - { - sfRenderWindow_drawSprite(window.CPointer, CPointer, ref marshaledStates); - } - else if (target is RenderTexture texture) - { - sfRenderTexture_drawSprite(texture.CPointer, CPointer, ref marshaledStates); - } + sfRenderWindow_drawSprite(window.CPointer, CPointer, ref marshaledStates); } + else if (target is RenderTexture texture) + { + sfRenderTexture_drawSprite(texture.CPointer, CPointer, ref marshaledStates); + } + } - //////////////////////////////////////////////////////////// - /// - /// Handle the destruction of the object - /// - /// Is the GC disposing the object, or is it an explicit call ? - //////////////////////////////////////////////////////////// - protected override void Destroy(bool disposing) => sfSprite_destroy(CPointer); + //////////////////////////////////////////////////////////// + /// + /// Handle the destruction of the object + /// + /// Is the GC disposing the object, or is it an explicit call ? + //////////////////////////////////////////////////////////// + protected override void Destroy(bool disposing) => sfSprite_destroy(CPointer); - private Texture _texture; + private Texture _texture; - #region Imports + #region Imports - [DllImport(CSFML.Graphics, CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] - private static extern IntPtr sfSprite_create(IntPtr texture); + [DllImport(CSFML.Graphics, CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] + private static extern IntPtr sfSprite_create(IntPtr texture); - [DllImport(CSFML.Graphics, CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] - private static extern IntPtr sfSprite_copy(IntPtr sprite); + [DllImport(CSFML.Graphics, CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] + private static extern IntPtr sfSprite_copy(IntPtr sprite); - [DllImport(CSFML.Graphics, CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] - private static extern void sfSprite_destroy(IntPtr cPointer); + [DllImport(CSFML.Graphics, CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] + private static extern void sfSprite_destroy(IntPtr cPointer); - [DllImport(CSFML.Graphics, CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] - private static extern void sfSprite_setColor(IntPtr cPointer, Color color); + [DllImport(CSFML.Graphics, CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] + private static extern void sfSprite_setColor(IntPtr cPointer, Color color); - [DllImport(CSFML.Graphics, CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] - private static extern Color sfSprite_getColor(IntPtr cPointer); + [DllImport(CSFML.Graphics, CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] + private static extern Color sfSprite_getColor(IntPtr cPointer); - [DllImport(CSFML.Graphics, CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] - private static extern void sfRenderWindow_drawSprite(IntPtr cPointer, IntPtr sprite, ref RenderStates.MarshalData states); + [DllImport(CSFML.Graphics, CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] + private static extern void sfRenderWindow_drawSprite(IntPtr cPointer, IntPtr sprite, ref RenderStates.MarshalData states); - [DllImport(CSFML.Graphics, CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] - private static extern void sfRenderTexture_drawSprite(IntPtr cPointer, IntPtr sprite, ref RenderStates.MarshalData states); + [DllImport(CSFML.Graphics, CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] + private static extern void sfRenderTexture_drawSprite(IntPtr cPointer, IntPtr sprite, ref RenderStates.MarshalData states); - [DllImport(CSFML.Graphics, CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] - private static extern void sfSprite_setTexture(IntPtr cPointer, IntPtr texture, bool adjustToNewSize); + [DllImport(CSFML.Graphics, CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] + private static extern void sfSprite_setTexture(IntPtr cPointer, IntPtr texture, bool adjustToNewSize); - [DllImport(CSFML.Graphics, CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] - private static extern void sfSprite_setTextureRect(IntPtr cPointer, IntRect rect); + [DllImport(CSFML.Graphics, CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] + private static extern void sfSprite_setTextureRect(IntPtr cPointer, IntRect rect); - [DllImport(CSFML.Graphics, CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] - private static extern IntRect sfSprite_getTextureRect(IntPtr cPointer); + [DllImport(CSFML.Graphics, CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] + private static extern IntRect sfSprite_getTextureRect(IntPtr cPointer); - [DllImport(CSFML.Graphics, CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] - private static extern FloatRect sfSprite_getLocalBounds(IntPtr cPointer); - #endregion - } + [DllImport(CSFML.Graphics, CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] + private static extern FloatRect sfSprite_getLocalBounds(IntPtr cPointer); + #endregion } diff --git a/src/SFML.Graphics/StencilMode.cs b/src/SFML.Graphics/StencilMode.cs index a0a40c9a..9e758cba 100644 --- a/src/SFML.Graphics/StencilMode.cs +++ b/src/SFML.Graphics/StencilMode.cs @@ -1,197 +1,196 @@ using System.Runtime.InteropServices; -namespace SFML.Graphics +namespace SFML.Graphics; + +//////////////////////////////////////////////////////// +/// +/// Enumeration of the stencil test comparisons that can be performed +/// +/// The comparisons are mapped directly to their OpenGL equivalents, +/// specified by glStencilFunc(). +/// +//////////////////////////////////////////////////////// +public enum StencilComparison { - //////////////////////////////////////////////////////// - /// - /// Enumeration of the stencil test comparisons that can be performed - /// - /// The comparisons are mapped directly to their OpenGL equivalents, - /// specified by glStencilFunc(). - /// - //////////////////////////////////////////////////////// - public enum StencilComparison - { - /// The stencil test never passes - Never, + /// The stencil test never passes + Never, + + /// The stencil test passes if the new value is less than the value in the stencil buffer + Less, - /// The stencil test passes if the new value is less than the value in the stencil buffer - Less, + /// The stencil test passes if the new value is less than or equal to 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 - LessEqual, + /// The stencil test passes if the new value is greater than the value in the stencil buffer + Greater, - /// The stencil test passes if the new value is greater than the value in the stencil buffer - Greater, + /// The stencil test passes if the new value is greater than or equal to 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 - GreaterEqual, + /// The stencil test passes if the new value is strictly 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 - Equal, + /// The stencil test passes if the new value is strictly inequal to the value in the stencil buffer + NotEqual, + + /// The stencil test always passes + Always +} + +//////////////////////////////////////////////////////// +/// +/// Enumeration of the stencil buffer update operations +/// +/// The update operations are mapped directly to their OpenGL equivalents, +/// specified by glStencilOp(). +/// +//////////////////////////////////////////////////////// +public enum StencilUpdateOperation +{ + /// If the stencil test passes, the value in the stencil buffer is not modified + Keep, - /// The stencil test passes if the new value is strictly inequal to the value in the stencil buffer - NotEqual, + /// If the stencil test passes, the value in the stencil buffer is set to zero + Zero, - /// The stencil test always passes - Always - } + /// If the stencil test passes, the value in the stencil buffer is set to the new value + Replace, - //////////////////////////////////////////////////////// + /// If the stencil test passes, the value in the stencil buffer is incremented and if required clamped + Increment, + + /// If the stencil test passes, the value in the stencil buffer is decremented and if required clamped + Decrement, + + /// If the stencil test passes, the value in the stencil buffer is bitwise inverted + Invert +} + +//////////////////////////////////////////////////////// +/// +/// Stencil value type (also used as a mask) +/// +//////////////////////////////////////////////////////// +[StructLayout(LayoutKind.Sequential)] +public struct StencilValue +{ + //////////////////////////////////////////////////////////// /// - /// Enumeration of the stencil buffer update operations - /// - /// The update operations are mapped directly to their OpenGL equivalents, - /// specified by glStencilOp(). + /// The stored stencil value /// - //////////////////////////////////////////////////////// - public enum StencilUpdateOperation - { - /// If the stencil test passes, the value in the stencil buffer is not modified - Keep, + //////////////////////////////////////////////////////////// + public uint Value; + + //////////////////////////////////////////////////////////// + /// + /// Convert a signed integer to a stencil value + /// + //////////////////////////////////////////////////////////// + public static explicit operator StencilValue(int value) => new() { Value = (uint)value }; + + //////////////////////////////////////////////////////////// + /// + /// Convert an unsigned integer to a stencil value + /// + //////////////////////////////////////////////////////////// + public static explicit operator StencilValue(uint value) => new() { Value = value }; +} - /// If the stencil test passes, the value in the stencil buffer is set to zero - Zero, +//////////////////////////////////////////////////////////// +/// +/// Stencil modes for drawing +/// +//////////////////////////////////////////////////////////// +[StructLayout(LayoutKind.Sequential)] +public struct StencilMode +{ + /// + /// The comparison we're performing the stencil test with + /// + public StencilComparison StencilComparison; - /// If the stencil test passes, the value in the stencil buffer is set to the new value - Replace, + /// + /// The update operation to perform if the stencil test passes + /// + public StencilUpdateOperation StencilUpdateOperation; - /// If the stencil test passes, the value in the stencil buffer is incremented and if required clamped - Increment, + /// + /// The reference value we're performing the stencil test with + /// + public uint StencilReference; - /// If the stencil test passes, the value in the stencil buffer is decremented and if required clamped - Decrement, + /// + /// The mask to apply to both the reference value and the value in the stencil buffer + /// + public uint StencilMask; - /// If the stencil test passes, the value in the stencil buffer is bitwise inverted - Invert - } + /// + /// Whether we should update the color buffer in addition to the stencil buffer + /// + [MarshalAs(UnmanagedType.I1)] + public bool StencilOnly; - //////////////////////////////////////////////////////// /// - /// Stencil value type (also used as a mask) + /// Default values for stencil mode /// - //////////////////////////////////////////////////////// - [StructLayout(LayoutKind.Sequential)] - public struct StencilValue + public static readonly StencilMode Default = new() { - //////////////////////////////////////////////////////////// - /// - /// The stored stencil value - /// - //////////////////////////////////////////////////////////// - public uint Value; - - //////////////////////////////////////////////////////////// - /// - /// Convert a signed integer to a stencil value - /// - //////////////////////////////////////////////////////////// - public static explicit operator StencilValue(int value) => new StencilValue() { Value = (uint)value }; - - //////////////////////////////////////////////////////////// - /// - /// Convert an unsigned integer to a stencil value - /// - //////////////////////////////////////////////////////////// - public static explicit operator StencilValue(uint value) => new StencilValue() { Value = value }; - } + StencilComparison = StencilComparison.Always, + StencilUpdateOperation = StencilUpdateOperation.Keep, + StencilReference = 0, + StencilMask = ~0u, + StencilOnly = false + }; //////////////////////////////////////////////////////////// /// - /// Stencil modes for drawing + /// Compare two stencil modes and checks if they are equal /// + /// Stencil Modes are equal //////////////////////////////////////////////////////////// - [StructLayout(LayoutKind.Sequential)] - public struct StencilMode - { - /// - /// The comparison we're performing the stencil test with - /// - public StencilComparison StencilComparison; - - /// - /// The update operation to perform if the stencil test passes - /// - public StencilUpdateOperation StencilUpdateOperation; - - /// - /// The reference value we're performing the stencil test with - /// - public uint StencilReference; - - /// - /// The mask to apply to both the reference value and the value in the stencil buffer - /// - public uint StencilMask; - - /// - /// Whether we should update the color buffer in addition to the stencil buffer - /// - [MarshalAs(UnmanagedType.I1)] - public bool StencilOnly; - - /// - /// Default values for stencil mode - /// - public static readonly StencilMode Default = new StencilMode() - { - StencilComparison = StencilComparison.Always, - StencilUpdateOperation = StencilUpdateOperation.Keep, - StencilReference = 0, - StencilMask = ~0u, - StencilOnly = false - }; - - //////////////////////////////////////////////////////////// - /// - /// Compare two stencil modes and checks if they are equal - /// - /// Stencil Modes are equal - //////////////////////////////////////////////////////////// - public static bool operator ==(StencilMode left, StencilMode right) => left.Equals(right); - - //////////////////////////////////////////////////////////// - /// - /// Compare two stencil modes and checks if they are not equal - /// - /// Stencil Modes are not equal - //////////////////////////////////////////////////////////// - public static bool operator !=(StencilMode left, StencilMode right) => !left.Equals(right); - - //////////////////////////////////////////////////////////// - /// - /// Compare stencil mode and object and checks if they are equal - /// - /// Object to check - /// Object and stencil mode are equal - //////////////////////////////////////////////////////////// - public override bool Equals(object obj) => obj is StencilMode mode && Equals(mode); - - //////////////////////////////////////////////////////////// - /// - /// Provide a integer describing the object - /// - /// Integer description of the object - //////////////////////////////////////////////////////////// - public override int GetHashCode() => - StencilComparison.GetHashCode() ^ - StencilUpdateOperation.GetHashCode() ^ - StencilReference.GetHashCode() ^ - StencilMask.GetHashCode() ^ - StencilOnly.GetHashCode(); - - /////////////////////////////////////////////////////////// - /// - /// Compare two stencil modes and checks if they are equal - /// - /// Stencil mode to check - /// Stencil modes are equal - //////////////////////////////////////////////////////////// - public bool Equals(StencilMode other) => - StencilComparison == other.StencilComparison && - StencilUpdateOperation == other.StencilUpdateOperation && - StencilReference == other.StencilReference && - StencilMask == other.StencilMask && - StencilOnly == other.StencilOnly; - } + public static bool operator ==(StencilMode left, StencilMode right) => left.Equals(right); + + //////////////////////////////////////////////////////////// + /// + /// Compare two stencil modes and checks if they are not equal + /// + /// Stencil Modes are not equal + //////////////////////////////////////////////////////////// + public static bool operator !=(StencilMode left, StencilMode right) => !left.Equals(right); + + //////////////////////////////////////////////////////////// + /// + /// Provide a integer describing the object + /// + /// Integer description of the object + //////////////////////////////////////////////////////////// + public override int GetHashCode() => + StencilComparison.GetHashCode() ^ + StencilUpdateOperation.GetHashCode() ^ + StencilReference.GetHashCode() ^ + StencilMask.GetHashCode() ^ + StencilOnly.GetHashCode(); + + //////////////////////////////////////////////////////////// + /// + /// Compare stencil mode and object and checks if they are equal + /// + /// Object to check + /// Object and stencil mode are equal + //////////////////////////////////////////////////////////// + public override readonly bool Equals(object obj) => obj is StencilMode mode && Equals(mode); + + /////////////////////////////////////////////////////////// + /// + /// Compare two stencil modes and checks if they are equal + /// + /// Stencil mode to check + /// Stencil modes are equal + //////////////////////////////////////////////////////////// + public readonly bool Equals(StencilMode other) => + StencilComparison == other.StencilComparison && + StencilUpdateOperation == other.StencilUpdateOperation && + StencilReference == other.StencilReference && + StencilMask == other.StencilMask && + StencilOnly == other.StencilOnly; } diff --git a/src/SFML.Graphics/Text.cs b/src/SFML.Graphics/Text.cs index 3e869f7c..6d4608fa 100644 --- a/src/SFML.Graphics/Text.cs +++ b/src/SFML.Graphics/Text.cs @@ -4,421 +4,417 @@ using System.Text; using SFML.System; -namespace SFML.Graphics +namespace SFML.Graphics; + +//////////////////////////////////////////////////////////// +/// +/// This class defines a graphical 2D text, that can be drawn on screen +/// +/// +/// See also the note on coordinates and undistorted rendering in SFML.Graphics.Transformable. +/// +//////////////////////////////////////////////////////////// +public class Text : Transformable, IDrawable { //////////////////////////////////////////////////////////// /// - /// This class defines a graphical 2D text, that can be drawn on screen + /// Flags for styles that can be applied to the /// - /// - /// See also the note on coordinates and undistorted rendering in SFML.Graphics.Transformable. - /// //////////////////////////////////////////////////////////// - public class Text : Transformable, IDrawable + [Flags] + public enum Styles { - //////////////////////////////////////////////////////////// - /// - /// Flags for styles that can be applied to the - /// - //////////////////////////////////////////////////////////// - [Flags] - public enum Styles - { - /// No Style - Regular = 0, + /// No Style + Regular = 0, - /// Bold - Bold = 1 << 0, + /// Bold + Bold = 1 << 0, - /// Italic - Italic = 1 << 1, + /// Italic + Italic = 1 << 1, - /// Underlined - Underlined = 1 << 2, + /// Underlined + Underlined = 1 << 2, - /// Strikethrough - StrikeThrough = 1 << 3 - } + /// Strikethrough + StrikeThrough = 1 << 3 + } - //////////////////////////////////////////////////////////// - /// - /// Construct the text from a - /// - /// Font to use - //////////////////////////////////////////////////////////// - public Text(Font font) : - this(font, "", 30) - { - } + //////////////////////////////////////////////////////////// + /// + /// Construct the text from a + /// + /// Font to use + //////////////////////////////////////////////////////////// + public Text(Font font) : + this(font, "", 30) + { + } - //////////////////////////////////////////////////////////// - /// - /// Construct the text from a string and a - /// - /// Font to use - /// String to display - //////////////////////////////////////////////////////////// - public Text(Font font, string str) : - this(font, str, 30) - { - } + //////////////////////////////////////////////////////////// + /// + /// Construct the text from a string and a + /// + /// Font to use + /// String to display + //////////////////////////////////////////////////////////// + public Text(Font font, string str) : + this(font, str, 30) + { + } - //////////////////////////////////////////////////////////// - /// - /// Construct the text from a string, and size - /// - /// Font to use - /// String to display - /// Font size - //////////////////////////////////////////////////////////// - public Text(Font font, string str, uint characterSize) : - base(sfText_create(font.CPointer)) - { - DisplayedString = str; - Font = font; - CharacterSize = characterSize; - } + //////////////////////////////////////////////////////////// + /// + /// Construct the text from a string, and size + /// + /// Font to use + /// String to display + /// Font size + //////////////////////////////////////////////////////////// + public Text(Font font, string str, uint characterSize) : + base(sfText_create(font.CPointer)) + { + DisplayedString = str; + Font = font; + CharacterSize = characterSize; + } - //////////////////////////////////////////////////////////// - /// - /// Construct the text from another - /// - /// Text to copy - //////////////////////////////////////////////////////////// - public Text(Text copy) : - base(sfText_copy(copy.CPointer)) - { - Origin = copy.Origin; - Position = copy.Position; - Rotation = copy.Rotation; - Scale = copy.Scale; + //////////////////////////////////////////////////////////// + /// + /// Construct the text from another + /// + /// Text to copy + //////////////////////////////////////////////////////////// + public Text(Text copy) : + base(sfText_copy(copy.CPointer)) + { + Origin = copy.Origin; + Position = copy.Position; + Rotation = copy.Rotation; + Scale = copy.Scale; - Font = copy.Font; - } + Font = copy.Font; + } - //////////////////////////////////////////////////////////// - /// - /// Fill of the - /// - /// - /// - /// By default, the text's fill is opaque White. - /// - /// Setting the fill color to a transparent with an outline - /// will cause the outline to be displayed in the fill area of the text. - /// - /// - //////////////////////////////////////////////////////////// - public Color FillColor - { - get => sfText_getFillColor(CPointer); - set => sfText_setFillColor(CPointer, value); - } + //////////////////////////////////////////////////////////// + /// + /// Fill of the + /// + /// + /// + /// By default, the text's fill is opaque White. + /// + /// Setting the fill color to a transparent with an outline + /// will cause the outline to be displayed in the fill area of the text. + /// + /// + //////////////////////////////////////////////////////////// + public Color FillColor + { + get => sfText_getFillColor(CPointer); + set => sfText_setFillColor(CPointer, value); + } - //////////////////////////////////////////////////////////// - /// - /// Outline of the - /// - /// - /// - /// By default, the text's outline is opaque Black. - /// - //////////////////////////////////////////////////////////// - public Color OutlineColor - { - get => sfText_getOutlineColor(CPointer); - set => sfText_setOutlineColor(CPointer, value); - } + //////////////////////////////////////////////////////////// + /// + /// Outline of the + /// + /// + /// + /// By default, the text's outline is opaque Black. + /// + //////////////////////////////////////////////////////////// + public Color OutlineColor + { + get => sfText_getOutlineColor(CPointer); + set => sfText_setOutlineColor(CPointer, value); + } - //////////////////////////////////////////////////////////// - /// - /// Thickness of the object's outline - /// - /// - /// - /// By default, the outline thickness is 0. - /// Be aware that using a negative value for the outline - /// thickness will cause distorted rendering. - /// - //////////////////////////////////////////////////////////// - public float OutlineThickness - { - get => sfText_getOutlineThickness(CPointer); - set => sfText_setOutlineThickness(CPointer, value); - } + //////////////////////////////////////////////////////////// + /// + /// Thickness of the object's outline + /// + /// + /// + /// By default, the outline thickness is 0. + /// Be aware that using a negative value for the outline + /// thickness will cause distorted rendering. + /// + //////////////////////////////////////////////////////////// + public float OutlineThickness + { + get => sfText_getOutlineThickness(CPointer); + set => sfText_setOutlineThickness(CPointer, value); + } - //////////////////////////////////////////////////////////// - /// - /// String which is displayed - /// - //////////////////////////////////////////////////////////// - public string DisplayedString + //////////////////////////////////////////////////////////// + /// + /// String which is displayed + /// + //////////////////////////////////////////////////////////// + public string DisplayedString + { + get { - get - { - // Get a pointer to the source string (UTF-32) - var source = sfText_getUnicodeString(CPointer); + // Get a pointer to the source string (UTF-32) + var source = sfText_getUnicodeString(CPointer); - // Find its length (find the terminating 0) - uint length = 0; - unsafe + // Find its length (find the terminating 0) + uint length = 0; + unsafe + { + for (var ptr = (uint*)source.ToPointer(); *ptr != 0; ++ptr) { - for (var ptr = (uint*)source.ToPointer(); *ptr != 0; ++ptr) - { - length++; - } + length++; } + } - // Copy it to a byte array - var sourceBytes = new byte[length * 4]; - Marshal.Copy(source, sourceBytes, 0, sourceBytes.Length); + // Copy it to a byte array + var sourceBytes = new byte[length * 4]; + Marshal.Copy(source, sourceBytes, 0, sourceBytes.Length); - // Convert it to a C# string - return Encoding.UTF32.GetString(sourceBytes); - } + // Convert it to a C# string + return Encoding.UTF32.GetString(sourceBytes); + } - set - { - // Copy the string to a null-terminated UTF-32 byte array - var utf32 = Encoding.UTF32.GetBytes(value + '\0'); + set + { + // Copy the string to a null-terminated UTF-32 byte array + var utf32 = Encoding.UTF32.GetBytes(value + '\0'); - // Pass it to the C API - unsafe + // Pass it to the C API + unsafe + { + fixed (byte* ptr = utf32) { - fixed (byte* ptr = utf32) - { - sfText_setUnicodeString(CPointer, (IntPtr)ptr); - } + sfText_setUnicodeString(CPointer, (IntPtr)ptr); } } } + } - //////////////////////////////////////////////////////////// - /// - /// used to display the text - /// - //////////////////////////////////////////////////////////// - public Font Font - { - get => _font; - set { _font = value; sfText_setFont(CPointer, value != null ? value.CPointer : IntPtr.Zero); } - } + //////////////////////////////////////////////////////////// + /// + /// used to display the text + /// + //////////////////////////////////////////////////////////// + public Font Font + { + get => _font; + set { _font = value; sfText_setFont(CPointer, value?.CPointer ?? IntPtr.Zero); } + } - //////////////////////////////////////////////////////////// - /// - /// Base size of characters - /// - //////////////////////////////////////////////////////////// - public uint CharacterSize - { - get => sfText_getCharacterSize(CPointer); - set => sfText_setCharacterSize(CPointer, value); - } + //////////////////////////////////////////////////////////// + /// + /// Base size of characters + /// + //////////////////////////////////////////////////////////// + public uint CharacterSize + { + get => sfText_getCharacterSize(CPointer); + set => sfText_setCharacterSize(CPointer, value); + } - //////////////////////////////////////////////////////////// - /// - /// Size of the letter spacing factor - /// - //////////////////////////////////////////////////////////// - public float LetterSpacing - { - get => sfText_getLetterSpacing(CPointer); - set => sfText_setLetterSpacing(CPointer, value); - } + //////////////////////////////////////////////////////////// + /// + /// Size of the letter spacing factor + /// + //////////////////////////////////////////////////////////// + public float LetterSpacing + { + get => sfText_getLetterSpacing(CPointer); + set => sfText_setLetterSpacing(CPointer, value); + } - //////////////////////////////////////////////////////////// - /// - /// Size of the line spacing factor - /// - //////////////////////////////////////////////////////////// - public float LineSpacing - { - get => sfText_getLineSpacing(CPointer); - set => sfText_setLineSpacing(CPointer, value); - } + //////////////////////////////////////////////////////////// + /// + /// Size of the line spacing factor + /// + //////////////////////////////////////////////////////////// + public float LineSpacing + { + get => sfText_getLineSpacing(CPointer); + set => sfText_setLineSpacing(CPointer, value); + } - //////////////////////////////////////////////////////////// - /// - /// Style of the text - /// - //////////////////////////////////////////////////////////// - public Styles Style + //////////////////////////////////////////////////////////// + /// + /// Style of the text + /// + //////////////////////////////////////////////////////////// + public Styles Style + { + get => sfText_getStyle(CPointer); + set => sfText_setStyle(CPointer, value); + } + + //////////////////////////////////////////////////////////// + /// + /// Return the visual position of the Index-th character of the text, + /// in coordinates relative to the text + /// + /// + /// Translation, origin, rotation and scale are not applied. + /// + /// Index of the character + /// Position of the Index-th character (end of text if Index is out of range) + //////////////////////////////////////////////////////////// + public Vector2f FindCharacterPos(uint index) => sfText_findCharacterPos(CPointer, (UIntPtr)index); + + //////////////////////////////////////////////////////////// + /// + /// Get the local bounding of the text. + /// + /// + /// The returned is in local coordinates. + /// Transformations (Translation, Rotation, Scale) are not applied to the entity. + /// In other words, this function returns the bounds of the + /// entity in the entity's coordinate system. + /// + /// Local bounding rectangle of the entity + //////////////////////////////////////////////////////////// + public FloatRect GetLocalBounds() => sfText_getLocalBounds(CPointer); + + //////////////////////////////////////////////////////////// + /// + /// Get the global bounding rectangle of the text. + /// + /// + /// The returned is in global coordinates. + /// Transformations (Translation, Rotation, Scale) are applied to the entity. + /// In other words, this function returns the bounds of the + /// sprite in the global 2D world's coordinate system. + /// + /// Global bounding rectangle of the entity + //////////////////////////////////////////////////////////// + public FloatRect GetGlobalBounds() => Transform.TransformRect(GetLocalBounds()); // we don't use the native getGlobalBounds function, because we override the object's transform + + //////////////////////////////////////////////////////////// + /// + /// Provide a string describing the object + /// + /// String description of the object + //////////////////////////////////////////////////////////// + public override string ToString() + { + if (IsInvalid) { - get => sfText_getStyle(CPointer); - set => sfText_setStyle(CPointer, value); + return MakeDisposedObjectString(); } - //////////////////////////////////////////////////////////// - /// - /// Return the visual position of the Index-th character of the text, - /// in coordinates relative to the text - /// - /// - /// Translation, origin, rotation and scale are not applied. - /// - /// Index of the character - /// Position of the Index-th character (end of text if Index is out of range) - //////////////////////////////////////////////////////////// - public Vector2f FindCharacterPos(uint index) => sfText_findCharacterPos(CPointer, (UIntPtr)index); - - //////////////////////////////////////////////////////////// - /// - /// Get the local bounding of the text. - /// - /// - /// The returned is in local coordinates. - /// Transformations (Translation, Rotation, Scale) are not applied to the entity. - /// In other words, this function returns the bounds of the - /// entity in the entity's coordinate system. - /// - /// Local bounding rectangle of the entity - //////////////////////////////////////////////////////////// - public FloatRect GetLocalBounds() => sfText_getLocalBounds(CPointer); - - //////////////////////////////////////////////////////////// - /// - /// Get the global bounding rectangle of the text. - /// - /// - /// The returned is in global coordinates. - /// Transformations (Translation, Rotation, Scale) are applied to the entity. - /// In other words, this function returns the bounds of the - /// sprite in the global 2D world's coordinate system. - /// - /// Global bounding rectangle of the entity - //////////////////////////////////////////////////////////// - public FloatRect GetGlobalBounds() => - // we don't use the native getGlobalBounds function, - // because we override the object's transform - Transform.TransformRect(GetLocalBounds()); - - //////////////////////////////////////////////////////////// - /// - /// Provide a string describing the object - /// - /// String description of the object - //////////////////////////////////////////////////////////// - public override string ToString() - { - if (IsInvalid) - { - return MakeDisposedObjectString(); - } - - return "[Text]" + - " FillColor(" + FillColor + ")" + - " OutlineColor(" + OutlineColor + ")" + - " String(" + DisplayedString + ")" + - " Font(" + Font + ")" + - " CharacterSize(" + CharacterSize + ")" + - " OutlineThickness(" + OutlineThickness + ")" + - " Style(" + Style + ")"; - } + return "[Text]" + + " FillColor(" + FillColor + ")" + + " OutlineColor(" + OutlineColor + ")" + + " String(" + DisplayedString + ")" + + " Font(" + Font + ")" + + " CharacterSize(" + CharacterSize + ")" + + " OutlineThickness(" + OutlineThickness + ")" + + " Style(" + Style + ")"; + } - //////////////////////////////////////////////////////////// - /// - /// Draw the text to a - /// - /// Render target to draw to - /// Current render states - //////////////////////////////////////////////////////////// - public void Draw(IRenderTarget target, RenderStates states) - { - states.Transform *= Transform; - var marshaledStates = states.Marshal(); + //////////////////////////////////////////////////////////// + /// + /// Draw the text to a + /// + /// Render target to draw to + /// Current render states + //////////////////////////////////////////////////////////// + public void Draw(IRenderTarget target, RenderStates states) + { + states.Transform *= Transform; + var marshaledStates = states.Marshal(); - if (target is RenderWindow window) - { - sfRenderWindow_drawText(window.CPointer, CPointer, ref marshaledStates); - } - else if (target is RenderTexture texture) - { - sfRenderTexture_drawText(texture.CPointer, CPointer, ref marshaledStates); - } + if (target is RenderWindow window) + { + sfRenderWindow_drawText(window.CPointer, CPointer, ref marshaledStates); } + else if (target is RenderTexture texture) + { + sfRenderTexture_drawText(texture.CPointer, CPointer, ref marshaledStates); + } + } - //////////////////////////////////////////////////////////// - /// - /// Handle the destruction of the object - /// - /// Is the GC disposing the object, or is it an explicit call ? - //////////////////////////////////////////////////////////// - protected override void Destroy(bool disposing) => sfText_destroy(CPointer); + //////////////////////////////////////////////////////////// + /// + /// Handle the destruction of the object + /// + /// Is the GC disposing the object, or is it an explicit call ? + //////////////////////////////////////////////////////////// + protected override void Destroy(bool disposing) => sfText_destroy(CPointer); - private Font _font; + private Font _font; - #region Imports - [DllImport(CSFML.Graphics, CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] - private static extern IntPtr sfText_create(IntPtr font); + #region Imports + [DllImport(CSFML.Graphics, CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] + private static extern IntPtr sfText_create(IntPtr font); - [DllImport(CSFML.Graphics, CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] - private static extern IntPtr sfText_copy(IntPtr text); + [DllImport(CSFML.Graphics, CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] + private static extern IntPtr sfText_copy(IntPtr text); - [DllImport(CSFML.Graphics, CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] - private static extern void sfText_destroy(IntPtr cPointer); + [DllImport(CSFML.Graphics, CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] + private static extern void sfText_destroy(IntPtr cPointer); - [DllImport(CSFML.Graphics, CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] - private static extern void sfText_setFillColor(IntPtr cPointer, Color color); + [DllImport(CSFML.Graphics, CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] + private static extern void sfText_setFillColor(IntPtr cPointer, Color color); - [DllImport(CSFML.Graphics, CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] - private static extern void sfText_setOutlineColor(IntPtr cPointer, Color color); + [DllImport(CSFML.Graphics, CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] + private static extern void sfText_setOutlineColor(IntPtr cPointer, Color color); - [DllImport(CSFML.Graphics, CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] - private static extern void sfText_setOutlineThickness(IntPtr cPointer, float thickness); + [DllImport(CSFML.Graphics, CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] + private static extern void sfText_setOutlineThickness(IntPtr cPointer, float thickness); - [DllImport(CSFML.Graphics, CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] - private static extern Color sfText_getFillColor(IntPtr cPointer); + [DllImport(CSFML.Graphics, CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] + private static extern Color sfText_getFillColor(IntPtr cPointer); - [DllImport(CSFML.Graphics, CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] - private static extern Color sfText_getOutlineColor(IntPtr cPointer); + [DllImport(CSFML.Graphics, CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] + private static extern Color sfText_getOutlineColor(IntPtr cPointer); - [DllImport(CSFML.Graphics, CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] - private static extern float sfText_getOutlineThickness(IntPtr cPointer); + [DllImport(CSFML.Graphics, CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] + private static extern float sfText_getOutlineThickness(IntPtr cPointer); - [DllImport(CSFML.Graphics, CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] - private static extern void sfRenderWindow_drawText(IntPtr cPointer, IntPtr text, ref RenderStates.MarshalData states); + [DllImport(CSFML.Graphics, CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] + private static extern void sfRenderWindow_drawText(IntPtr cPointer, IntPtr text, ref RenderStates.MarshalData states); - [DllImport(CSFML.Graphics, CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] - private static extern void sfRenderTexture_drawText(IntPtr cPointer, IntPtr text, ref RenderStates.MarshalData states); + [DllImport(CSFML.Graphics, CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] + private static extern void sfRenderTexture_drawText(IntPtr cPointer, IntPtr text, ref RenderStates.MarshalData states); - [DllImport(CSFML.Graphics, CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] - private static extern void sfText_setUnicodeString(IntPtr cPointer, IntPtr text); + [DllImport(CSFML.Graphics, CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] + private static extern void sfText_setUnicodeString(IntPtr cPointer, IntPtr text); - [DllImport(CSFML.Graphics, CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] - private static extern void sfText_setFont(IntPtr cPointer, IntPtr font); + [DllImport(CSFML.Graphics, CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] + private static extern void sfText_setFont(IntPtr cPointer, IntPtr font); - [DllImport(CSFML.Graphics, CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] - private static extern void sfText_setCharacterSize(IntPtr cPointer, uint size); + [DllImport(CSFML.Graphics, CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] + private static extern void sfText_setCharacterSize(IntPtr cPointer, uint size); - [DllImport(CSFML.Graphics, CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] - private static extern void sfText_setLineSpacing(IntPtr cPointer, float spacingFactor); + [DllImport(CSFML.Graphics, CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] + private static extern void sfText_setLineSpacing(IntPtr cPointer, float spacingFactor); - [DllImport(CSFML.Graphics, CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] - private static extern void sfText_setLetterSpacing(IntPtr cPointer, float spacingFactor); + [DllImport(CSFML.Graphics, CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] + private static extern void sfText_setLetterSpacing(IntPtr cPointer, float spacingFactor); - [DllImport(CSFML.Graphics, CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] - private static extern void sfText_setStyle(IntPtr cPointer, Styles style); + [DllImport(CSFML.Graphics, CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] + private static extern void sfText_setStyle(IntPtr cPointer, Styles style); - [DllImport(CSFML.Graphics, CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] - private static extern IntPtr sfText_getUnicodeString(IntPtr cPointer); + [DllImport(CSFML.Graphics, CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] + private static extern IntPtr sfText_getUnicodeString(IntPtr cPointer); - [DllImport(CSFML.Graphics, CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] - private static extern uint sfText_getCharacterSize(IntPtr cPointer); + [DllImport(CSFML.Graphics, CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] + private static extern uint sfText_getCharacterSize(IntPtr cPointer); - [DllImport(CSFML.Graphics, CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] - private static extern float sfText_getLetterSpacing(IntPtr cPointer); + [DllImport(CSFML.Graphics, CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] + private static extern float sfText_getLetterSpacing(IntPtr cPointer); - [DllImport(CSFML.Graphics, CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] - private static extern float sfText_getLineSpacing(IntPtr cPointer); + [DllImport(CSFML.Graphics, CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] + private static extern float sfText_getLineSpacing(IntPtr cPointer); - [DllImport(CSFML.Graphics, CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] - private static extern Styles sfText_getStyle(IntPtr cPointer); + [DllImport(CSFML.Graphics, CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] + private static extern Styles sfText_getStyle(IntPtr cPointer); - [DllImport(CSFML.Graphics, CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] - private static extern Vector2f sfText_findCharacterPos(IntPtr cPointer, UIntPtr index); + [DllImport(CSFML.Graphics, CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] + private static extern Vector2f sfText_findCharacterPos(IntPtr cPointer, UIntPtr index); - [DllImport(CSFML.Graphics, CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] - private static extern FloatRect sfText_getLocalBounds(IntPtr cPointer); - #endregion - } + [DllImport(CSFML.Graphics, CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] + private static extern FloatRect sfText_getLocalBounds(IntPtr cPointer); + #endregion } diff --git a/src/SFML.Graphics/Texture.cs b/src/SFML.Graphics/Texture.cs index 4bff8222..0eb02dee 100644 --- a/src/SFML.Graphics/Texture.cs +++ b/src/SFML.Graphics/Texture.cs @@ -5,608 +5,607 @@ using SFML.System; using SFML.Window; -namespace SFML.Graphics +namespace SFML.Graphics; + +//////////////////////////////////////////////////////////// +/// +/// Image living on the graphics card that can be used for drawing +/// +/// 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 load option is only useful in conjunction with an sRGB capable +/// framebuffer. This can be requested during window creation. +/// +//////////////////////////////////////////////////////////// +public class Texture : ObjectBase { //////////////////////////////////////////////////////////// /// - /// Image living on the graphics card that can be used for drawing - /// - /// 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 load option is only useful in conjunction with an sRGB capable - /// framebuffer. This can be requested during window creation. + /// Construct the texture /// + /// + /// Textures created this way are uninitialized and have indeterminate contents. + /// + /// Width and height of the texture + /// True to convert the texture source from sRGB, false otherwise + /// //////////////////////////////////////////////////////////// - public class Texture : ObjectBase + public Texture(Vector2u size, bool srgb = false) : + base(IntPtr.Zero) { - //////////////////////////////////////////////////////////// - /// - /// Construct the texture - /// - /// - /// Textures created this way are uninitialized and have indeterminate contents. - /// - /// Width and height of the texture - /// True to convert the texture source from sRGB, false otherwise - /// - //////////////////////////////////////////////////////////// - public Texture(Vector2u size, bool srgb = false) : - base(IntPtr.Zero) + if (srgb) { - if (srgb) - { - CPointer = sfTexture_createSrgb(size); - } - else - { - CPointer = sfTexture_create(size); - } - - if (IsInvalid) - { - throw new LoadingFailedException("texture"); - } + CPointer = sfTexture_createSrgb(size); } - - //////////////////////////////////////////////////////////// - /// - /// Construct the texture from a file - /// - /// Path of the image file to load - /// True to convert the texture source from sRGB, false otherwise - /// - //////////////////////////////////////////////////////////// - public Texture(string filename, bool srgb = false) : - this(filename, new IntRect((0, 0), (0, 0)), srgb) + else { + CPointer = sfTexture_create(size); } - //////////////////////////////////////////////////////////// - /// - /// Construct the texture from a file - /// - /// Path of the image file to load - /// Area of the image to load - /// True to convert the texture source from sRGB, false otherwise - /// - //////////////////////////////////////////////////////////// - public Texture(string filename, IntRect area, bool srgb = false) : - base(IntPtr.Zero) + if (IsInvalid) { - if (srgb) - { - CPointer = sfTexture_createSrgbFromFile(filename, ref area); - } - else - { - CPointer = sfTexture_createFromFile(filename, ref area); - } - - if (IsInvalid) - { - throw new LoadingFailedException("texture", filename); - } + throw new LoadingFailedException("texture"); } + } - //////////////////////////////////////////////////////////// - /// - /// Construct the texture from a file in a stream - /// - /// Stream containing the file contents - /// True to convert the texture source from sRGB, false otherwise - /// - //////////////////////////////////////////////////////////// - public Texture(Stream stream, bool srgb = false) : - this(stream, new IntRect((0, 0), (0, 0)), srgb) + //////////////////////////////////////////////////////////// + /// + /// Construct the texture from a file + /// + /// Path of the image file to load + /// True to convert the texture source from sRGB, false otherwise + /// + //////////////////////////////////////////////////////////// + public Texture(string filename, bool srgb = false) : + this(filename, new IntRect((0, 0), (0, 0)), srgb) + { + } + + //////////////////////////////////////////////////////////// + /// + /// Construct the texture from a file + /// + /// Path of the image file to load + /// Area of the image to load + /// True to convert the texture source from sRGB, false otherwise + /// + //////////////////////////////////////////////////////////// + public Texture(string filename, IntRect area, bool srgb = false) : + base(IntPtr.Zero) + { + if (srgb) { + CPointer = sfTexture_createSrgbFromFile(filename, ref area); } - - //////////////////////////////////////////////////////////// - /// - /// Construct the texture from a file in a stream - /// - /// Stream containing the file contents - /// Area of the image to load - /// True to convert the texture source from sRGB, false otherwise - /// - //////////////////////////////////////////////////////////// - public Texture(Stream stream, IntRect area, bool srgb = false) : - base(IntPtr.Zero) + else { - using (var adaptor = new StreamAdaptor(stream)) - { - if (srgb) - { - CPointer = sfTexture_createSrgbFromStream(adaptor.InputStreamPtr, ref area); - } - else - { - CPointer = sfTexture_createFromStream(adaptor.InputStreamPtr, ref area); - } - } - - if (IsInvalid) - { - throw new LoadingFailedException("texture"); - } + CPointer = sfTexture_createFromFile(filename, ref area); } - //////////////////////////////////////////////////////////// - /// - /// Construct the texture from an image - /// - /// Image to load to the texture - /// True to convert the texture source from sRGB, false otherwise - /// - //////////////////////////////////////////////////////////// - public Texture(Image image, bool srgb = false) : - this(image, new IntRect((0, 0), (0, 0)), srgb) + if (IsInvalid) { + throw new LoadingFailedException("texture", filename); } + } - //////////////////////////////////////////////////////////// - /// - /// Construct the texture from an image - /// - /// Image to load to the texture - /// Area of the image to load - /// True to convert the texture source from sRGB, false otherwise - /// - //////////////////////////////////////////////////////////// - public Texture(Image image, IntRect area, bool srgb = false) : - base(IntPtr.Zero) + //////////////////////////////////////////////////////////// + /// + /// Construct the texture from a file in a stream + /// + /// Stream containing the file contents + /// True to convert the texture source from sRGB, false otherwise + /// + //////////////////////////////////////////////////////////// + public Texture(Stream stream, bool srgb = false) : + this(stream, new IntRect((0, 0), (0, 0)), srgb) + { + } + + //////////////////////////////////////////////////////////// + /// + /// Construct the texture from a file in a stream + /// + /// Stream containing the file contents + /// Area of the image to load + /// True to convert the texture source from sRGB, false otherwise + /// + //////////////////////////////////////////////////////////// + public Texture(Stream stream, IntRect area, bool srgb = false) : + base(IntPtr.Zero) + { + using (var adaptor = new StreamAdaptor(stream)) { if (srgb) { - CPointer = sfTexture_createSrgbFromImage(image.CPointer, ref area); + CPointer = sfTexture_createSrgbFromStream(adaptor.InputStreamPtr, ref area); } else { - CPointer = sfTexture_createFromImage(image.CPointer, ref area); - } - - if (IsInvalid) - { - throw new LoadingFailedException("texture"); + CPointer = sfTexture_createFromStream(adaptor.InputStreamPtr, ref area); } } - //////////////////////////////////////////////////////////// - /// - /// Construct the texture from a file in memory - /// - /// Byte array containing the file contents - /// True to convert the texture source from sRGB, false otherwise - /// - //////////////////////////////////////////////////////////// - public Texture(byte[] bytes, bool srgb = false) : - this(bytes, new IntRect((0, 0), (0, 0)), srgb) + if (IsInvalid) { + throw new LoadingFailedException("texture"); } + } - //////////////////////////////////////////////////////////// - /// - /// Construct the texture from a file in memory - /// - /// Byte array containing the file contents - /// Area of the image to load - /// True to convert the texture source from sRGB, false otherwise - /// - //////////////////////////////////////////////////////////// - public Texture(byte[] bytes, IntRect area, bool srgb = false) : - base(IntPtr.Zero) - { - unsafe - { - fixed (void* ptr = bytes) - { - if (srgb) - { - CPointer = sfTexture_createSrgbFromMemory((IntPtr)ptr, (UIntPtr)bytes.Length, ref area); - } - else - { - CPointer = sfTexture_createFromMemory((IntPtr)ptr, (UIntPtr)bytes.Length, ref area); - } - } - } + //////////////////////////////////////////////////////////// + /// + /// Construct the texture from an image + /// + /// Image to load to the texture + /// True to convert the texture source from sRGB, false otherwise + /// + //////////////////////////////////////////////////////////// + public Texture(Image image, bool srgb = false) : + this(image, new IntRect((0, 0), (0, 0)), srgb) + { + } - if (IsInvalid) - { - throw new LoadingFailedException("texture"); - } + //////////////////////////////////////////////////////////// + /// + /// Construct the texture from an image + /// + /// Image to load to the texture + /// Area of the image to load + /// True to convert the texture source from sRGB, false otherwise + /// + //////////////////////////////////////////////////////////// + public Texture(Image image, IntRect area, bool srgb = false) : + base(IntPtr.Zero) + { + if (srgb) + { + CPointer = sfTexture_createSrgbFromImage(image.CPointer, ref area); + } + else + { + CPointer = sfTexture_createFromImage(image.CPointer, ref area); } - //////////////////////////////////////////////////////////// - /// - /// Construct the texture from another texture - /// - /// Texture to copy - //////////////////////////////////////////////////////////// - public Texture(Texture copy) : - base(sfTexture_copy(copy.CPointer)) + if (IsInvalid) { + throw new LoadingFailedException("texture"); } + } - //////////////////////////////////////////////////////////// - /// - /// Get the underlying OpenGL handle of the texture. - /// - /// - /// You shouldn't need to use this handle, unless you have - /// very specific stuff to implement that SFML doesn't support, - /// or implement a temporary workaround until a bug is fixed. - /// - //////////////////////////////////////////////////////////// - public uint NativeHandle => sfTexture_getNativeHandle(CPointer); - - //////////////////////////////////////////////////////////// - /// - /// Copy a texture's pixels to an image - /// - /// Image containing the texture's pixels - //////////////////////////////////////////////////////////// - public Image CopyToImage() => new Image(sfTexture_copyToImage(CPointer)); - - //////////////////////////////////////////////////////////// - /// - /// Resize the texture. - /// - /// Width and height of the texture - /// True to enable sRGB conversion, false to disable it - //////////////////////////////////////////////////////////// - public bool Resize(Vector2u size, bool srgb = false) => srgb ? sfTexture_resizeSrgb(CPointer, size) : sfTexture_resize(CPointer, size); - - //////////////////////////////////////////////////////////// - /// - /// Update a texture from an array of pixels - /// - /// Array of pixels to copy to the texture - //////////////////////////////////////////////////////////// - public void Update(byte[] pixels) => Update(pixels, Size, new Vector2u()); - - //////////////////////////////////////////////////////////// - /// - /// Update a texture from an array of pixels - /// - /// Array of pixels to copy to the texture - /// Width and height of the pixel region contained in pixels - /// Coordinates of the destination position - //////////////////////////////////////////////////////////// - public void Update(byte[] pixels, Vector2u size, Vector2u dest) + //////////////////////////////////////////////////////////// + /// + /// Construct the texture from a file in memory + /// + /// Byte array containing the file contents + /// True to convert the texture source from sRGB, false otherwise + /// + //////////////////////////////////////////////////////////// + public Texture(byte[] bytes, bool srgb = false) : + this(bytes, new IntRect((0, 0), (0, 0)), srgb) + { + } + + //////////////////////////////////////////////////////////// + /// + /// Construct the texture from a file in memory + /// + /// Byte array containing the file contents + /// Area of the image to load + /// True to convert the texture source from sRGB, false otherwise + /// + //////////////////////////////////////////////////////////// + public Texture(byte[] bytes, IntRect area, bool srgb = false) : + base(IntPtr.Zero) + { + unsafe { - unsafe + fixed (void* ptr = bytes) { - fixed (byte* ptr = pixels) + if (srgb) + { + CPointer = sfTexture_createSrgbFromMemory((IntPtr)ptr, (UIntPtr)bytes.Length, ref area); + } + else { - sfTexture_updateFromPixels(CPointer, ptr, size, dest); + CPointer = sfTexture_createFromMemory((IntPtr)ptr, (UIntPtr)bytes.Length, ref area); } } } - //////////////////////////////////////////////////////////// - /// - /// Update a part of this texture from another texture - /// - /// Source texture to copy to destination texture - /// Coordinates of the destination position - //////////////////////////////////////////////////////////// - public void Update(Texture texture, Vector2u dest) => sfTexture_updateFromTexture(CPointer, texture.CPointer, dest); - - //////////////////////////////////////////////////////////// - /// - /// Update a texture from an image - /// - /// Image to copy to the texture - //////////////////////////////////////////////////////////// - public void Update(Image image) => Update(image, new Vector2u()); - - //////////////////////////////////////////////////////////// - /// - /// Update a texture from an image - /// - /// Image to copy to the texture - /// Coordinates of the destination position - //////////////////////////////////////////////////////////// - public void Update(Image image, Vector2u dest) => sfTexture_updateFromImage(CPointer, image.CPointer, dest); - - //////////////////////////////////////////////////////////// - /// - /// Update a texture from the contents of a window - /// - /// Window to copy to the texture - //////////////////////////////////////////////////////////// - public void Update(SFML.Window.Window window) => Update(window, new Vector2u()); - - //////////////////////////////////////////////////////////// - /// - /// Update a texture from the contents of a window - /// - /// Window to copy to the texture - /// Coordinates of the destination position - //////////////////////////////////////////////////////////// - public void Update(SFML.Window.Window window, Vector2u dest) => sfTexture_updateFromWindow(CPointer, window.CPointer, dest); - - //////////////////////////////////////////////////////////// - /// - /// Update a texture from the contents of a render-window - /// - /// Render-window to copy to the texture - //////////////////////////////////////////////////////////// - public void Update(RenderWindow window) => Update(window, new Vector2u()); - - //////////////////////////////////////////////////////////// - /// - /// Update a texture from the contents of a render-window - /// - /// Render-window to copy to the texture - /// Coordinates of the destination position - //////////////////////////////////////////////////////////// - public void Update(RenderWindow window, Vector2u dest) => sfTexture_updateFromRenderWindow(CPointer, window.CPointer, dest); - - //////////////////////////////////////////////////////////// - /// - /// 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. - /// - /// - /// True if mipmap generation was successful, false if unsuccessful - //////////////////////////////////////////////////////////// - public bool GenerateMipmap() => sfTexture_generateMipmap(CPointer); - - //////////////////////////////////////////////////////////// - /// - /// Swap the contents of this texture with those of another - /// - /// Instance to swap with - //////////////////////////////////////////////////////////// - public void Swap(Texture right) => sfTexture_swap(CPointer, right.CPointer); - - //////////////////////////////////////////////////////////// - /// - /// Control the smooth filter - /// - //////////////////////////////////////////////////////////// - public bool Smooth + if (IsInvalid) { - get => sfTexture_isSmooth(CPointer); - set => sfTexture_setSmooth(CPointer, value); + throw new LoadingFailedException("texture"); } + } - //////////////////////////////////////////////////////////// - /// - /// Enable or disable conversion from sRGB - /// - /// - /// - /// 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. - /// - /// After enabling or disabling sRGB conversion, make sure to reload - /// the texture data in order for the setting to take effect. - /// - /// This option is only useful in conjunction with an sRGB capable - /// framebuffer. This can be requested during window creation. - /// - //////////////////////////////////////////////////////////// - public bool IsSrgb => sfTexture_isSrgb(CPointer); - - //////////////////////////////////////////////////////////// - /// - /// Control the repeat mode - /// - //////////////////////////////////////////////////////////// - public bool Repeated - { - get => sfTexture_isRepeated(CPointer); - set => sfTexture_setRepeated(CPointer, value); - } + //////////////////////////////////////////////////////////// + /// + /// Construct the texture from another texture + /// + /// Texture to copy + //////////////////////////////////////////////////////////// + public Texture(Texture copy) : + base(sfTexture_copy(copy.CPointer)) + { + } + + //////////////////////////////////////////////////////////// + /// + /// Get the underlying OpenGL handle of the texture. + /// + /// + /// You shouldn't need to use this handle, unless you have + /// very specific stuff to implement that SFML doesn't support, + /// or implement a temporary workaround until a bug is fixed. + /// + //////////////////////////////////////////////////////////// + public uint NativeHandle => sfTexture_getNativeHandle(CPointer); + + //////////////////////////////////////////////////////////// + /// + /// Copy a texture's pixels to an image + /// + /// Image containing the texture's pixels + //////////////////////////////////////////////////////////// + public Image CopyToImage() => new(sfTexture_copyToImage(CPointer)); + + //////////////////////////////////////////////////////////// + /// + /// Resize the texture. + /// + /// Width and height of the texture + /// True to enable sRGB conversion, false to disable it + //////////////////////////////////////////////////////////// + public bool Resize(Vector2u size, bool srgb = false) => srgb ? sfTexture_resizeSrgb(CPointer, size) : sfTexture_resize(CPointer, size); + + //////////////////////////////////////////////////////////// + /// + /// Update a texture from an array of pixels + /// + /// Array of pixels to copy to the texture + //////////////////////////////////////////////////////////// + public void Update(byte[] pixels) => Update(pixels, Size, new Vector2u()); - //////////////////////////////////////////////////////////// - /// - /// Size of the texture, in pixels - /// - //////////////////////////////////////////////////////////// - public Vector2u Size => sfTexture_getSize(CPointer); - - //////////////////////////////////////////////////////////// - /// - /// Bind a texture for rendering - /// - /// Shader to bind (can be null to use no texture) - /// Type of texture coordinates to use - //////////////////////////////////////////////////////////// - public static void Bind(Texture texture, CoordinateType type) => sfTexture_bind(texture != null ? texture.CPointer : IntPtr.Zero, type); - - //////////////////////////////////////////////////////////// - /// - /// Maximum texture size allowed - /// - //////////////////////////////////////////////////////////// - public static uint MaximumSize => sfTexture_getMaximumSize(); - - //////////////////////////////////////////////////////////// - /// - /// Provide a string describing the object - /// - /// String description of the object - //////////////////////////////////////////////////////////// - public override string ToString() + //////////////////////////////////////////////////////////// + /// + /// Update a texture from an array of pixels + /// + /// Array of pixels to copy to the texture + /// Width and height of the pixel region contained in pixels + /// Coordinates of the destination position + //////////////////////////////////////////////////////////// + public void Update(byte[] pixels, Vector2u size, Vector2u dest) + { + unsafe { - if (IsInvalid) + fixed (byte* ptr = pixels) { - return MakeDisposedObjectString(); + sfTexture_updateFromPixels(CPointer, ptr, size, dest); } + } + } + + //////////////////////////////////////////////////////////// + /// + /// Update a part of this texture from another texture + /// + /// Source texture to copy to destination texture + /// Coordinates of the destination position + //////////////////////////////////////////////////////////// + public void Update(Texture texture, Vector2u dest) => sfTexture_updateFromTexture(CPointer, texture.CPointer, dest); + + //////////////////////////////////////////////////////////// + /// + /// Update a texture from an image + /// + /// Image to copy to the texture + //////////////////////////////////////////////////////////// + public void Update(Image image) => Update(image, new Vector2u()); + + //////////////////////////////////////////////////////////// + /// + /// Update a texture from an image + /// + /// Image to copy to the texture + /// Coordinates of the destination position + //////////////////////////////////////////////////////////// + public void Update(Image image, Vector2u dest) => sfTexture_updateFromImage(CPointer, image.CPointer, dest); + + //////////////////////////////////////////////////////////// + /// + /// Update a texture from the contents of a window + /// + /// Window to copy to the texture + //////////////////////////////////////////////////////////// + public void Update(SFML.Window.Window window) => Update(window, new Vector2u()); + + //////////////////////////////////////////////////////////// + /// + /// Update a texture from the contents of a window + /// + /// Window to copy to the texture + /// Coordinates of the destination position + //////////////////////////////////////////////////////////// + public void Update(SFML.Window.Window window, Vector2u dest) => sfTexture_updateFromWindow(CPointer, window.CPointer, dest); + + //////////////////////////////////////////////////////////// + /// + /// Update a texture from the contents of a render-window + /// + /// Render-window to copy to the texture + //////////////////////////////////////////////////////////// + public void Update(RenderWindow window) => Update(window, new Vector2u()); + + //////////////////////////////////////////////////////////// + /// + /// Update a texture from the contents of a render-window + /// + /// Render-window to copy to the texture + /// Coordinates of the destination position + //////////////////////////////////////////////////////////// + public void Update(RenderWindow window, Vector2u dest) => sfTexture_updateFromRenderWindow(CPointer, window.CPointer, dest); + + //////////////////////////////////////////////////////////// + /// + /// 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. + /// + /// + /// True if mipmap generation was successful, false if unsuccessful + //////////////////////////////////////////////////////////// + public bool GenerateMipmap() => sfTexture_generateMipmap(CPointer); + + //////////////////////////////////////////////////////////// + /// + /// Swap the contents of this texture with those of another + /// + /// Instance to swap with + //////////////////////////////////////////////////////////// + public void Swap(Texture right) => sfTexture_swap(CPointer, right.CPointer); + + //////////////////////////////////////////////////////////// + /// + /// Control the smooth filter + /// + //////////////////////////////////////////////////////////// + public bool Smooth + { + get => sfTexture_isSmooth(CPointer); + set => sfTexture_setSmooth(CPointer, value); + } + + //////////////////////////////////////////////////////////// + /// + /// Enable or disable conversion from sRGB + /// + /// + /// + /// 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. + /// + /// After enabling or disabling sRGB conversion, make sure to reload + /// the texture data in order for the setting to take effect. + /// + /// This option is only useful in conjunction with an sRGB capable + /// framebuffer. This can be requested during window creation. + /// + //////////////////////////////////////////////////////////// + public bool IsSrgb => sfTexture_isSrgb(CPointer); + + //////////////////////////////////////////////////////////// + /// + /// Control the repeat mode + /// + //////////////////////////////////////////////////////////// + public bool Repeated + { + get => sfTexture_isRepeated(CPointer); + set => sfTexture_setRepeated(CPointer, value); + } + + //////////////////////////////////////////////////////////// + /// + /// Size of the texture, in pixels + /// + //////////////////////////////////////////////////////////// + public Vector2u Size => sfTexture_getSize(CPointer); + + //////////////////////////////////////////////////////////// + /// + /// Bind a texture for rendering + /// + /// Shader to bind (can be null to use no texture) + /// Type of texture coordinates to use + //////////////////////////////////////////////////////////// + public static void Bind(Texture texture, CoordinateType type) => sfTexture_bind(texture?.CPointer ?? IntPtr.Zero, type); - return "[Texture]" + - " Size(" + Size + ")" + - " Smooth(" + Smooth + ")" + - " Repeated(" + Repeated + ")"; + //////////////////////////////////////////////////////////// + /// + /// Maximum texture size allowed + /// + //////////////////////////////////////////////////////////// + public static uint MaximumSize => sfTexture_getMaximumSize(); + + //////////////////////////////////////////////////////////// + /// + /// Provide a string describing the object + /// + /// String description of the object + //////////////////////////////////////////////////////////// + public override string ToString() + { + if (IsInvalid) + { + return MakeDisposedObjectString(); } - //////////////////////////////////////////////////////////// - /// - /// Internal constructor - /// - /// Pointer to the object in C library - //////////////////////////////////////////////////////////// - internal Texture(IntPtr cPointer) : - base(cPointer) => _external = true; - - //////////////////////////////////////////////////////////// - /// - /// Handle the destruction of the object - /// - /// Is the GC disposing the object, or is it an explicit call ? - //////////////////////////////////////////////////////////// - protected override void Destroy(bool disposing) + return "[Texture]" + + " Size(" + Size + ")" + + " Smooth(" + Smooth + ")" + + " Repeated(" + Repeated + ")"; + } + + //////////////////////////////////////////////////////////// + /// + /// Internal constructor + /// + /// Pointer to the object in C library + //////////////////////////////////////////////////////////// + internal Texture(IntPtr cPointer) : + base(cPointer) => _external = true; + + //////////////////////////////////////////////////////////// + /// + /// Handle the destruction of the object + /// + /// Is the GC disposing the object, or is it an explicit call ? + //////////////////////////////////////////////////////////// + protected override void Destroy(bool disposing) + { + if (!_external) { - if (!_external) + if (!disposing) { - if (!disposing) - { - _ = Context.Global.SetActive(true); - } + _ = Context.Global.SetActive(true); + } - sfTexture_destroy(CPointer); + sfTexture_destroy(CPointer); - if (!disposing) - { - _ = Context.Global.SetActive(false); - } + if (!disposing) + { + _ = Context.Global.SetActive(false); } } + } - private readonly bool _external; + private readonly bool _external; - #region Imports - [DllImport(CSFML.Graphics, CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] - private static extern IntPtr sfTexture_create(Vector2u size); + #region Imports + [DllImport(CSFML.Graphics, CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] + private static extern IntPtr sfTexture_create(Vector2u size); - [DllImport(CSFML.Graphics, CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] - private static extern IntPtr sfTexture_createSrgb(Vector2u size); + [DllImport(CSFML.Graphics, CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] + private static extern IntPtr sfTexture_createSrgb(Vector2u size); - [DllImport(CSFML.Graphics, CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] - private static extern IntPtr sfTexture_createFromFile(string filename, ref IntRect area); + [DllImport(CSFML.Graphics, CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] + private static extern IntPtr sfTexture_createFromFile(string filename, ref IntRect area); - [DllImport(CSFML.Graphics, CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] - private static extern IntPtr sfTexture_createSrgbFromFile(string filename, ref IntRect area); + [DllImport(CSFML.Graphics, CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] + private static extern IntPtr sfTexture_createSrgbFromFile(string filename, ref IntRect area); - [DllImport(CSFML.Graphics, CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] - private static extern IntPtr sfTexture_createFromStream(IntPtr stream, ref IntRect area); + [DllImport(CSFML.Graphics, CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] + private static extern IntPtr sfTexture_createFromStream(IntPtr stream, ref IntRect area); - [DllImport(CSFML.Graphics, CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] - private static extern IntPtr sfTexture_createSrgbFromStream(IntPtr stream, ref IntRect area); + [DllImport(CSFML.Graphics, CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] + private static extern IntPtr sfTexture_createSrgbFromStream(IntPtr stream, ref IntRect area); - [DllImport(CSFML.Graphics, CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] - private static extern IntPtr sfTexture_createFromImage(IntPtr image, ref IntRect area); + [DllImport(CSFML.Graphics, CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] + private static extern IntPtr sfTexture_createFromImage(IntPtr image, ref IntRect area); - [DllImport(CSFML.Graphics, CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] - private static extern IntPtr sfTexture_createSrgbFromImage(IntPtr image, ref IntRect area); + [DllImport(CSFML.Graphics, CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] + private static extern IntPtr sfTexture_createSrgbFromImage(IntPtr image, ref IntRect area); - [DllImport(CSFML.Graphics, CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] - private static extern IntPtr sfTexture_createFromMemory(IntPtr data, UIntPtr size, ref IntRect area); + [DllImport(CSFML.Graphics, CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] + private static extern IntPtr sfTexture_createFromMemory(IntPtr data, UIntPtr size, ref IntRect area); - [DllImport(CSFML.Graphics, CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] - private static extern IntPtr sfTexture_createSrgbFromMemory(IntPtr data, UIntPtr size, ref IntRect area); + [DllImport(CSFML.Graphics, CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] + private static extern IntPtr sfTexture_createSrgbFromMemory(IntPtr data, UIntPtr size, ref IntRect area); - [DllImport(CSFML.Graphics, CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] - private static extern IntPtr sfTexture_copy(IntPtr texture); + [DllImport(CSFML.Graphics, CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] + private static extern IntPtr sfTexture_copy(IntPtr texture); - [DllImport(CSFML.Graphics, CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] - private static extern void sfTexture_destroy(IntPtr texture); + [DllImport(CSFML.Graphics, CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] + private static extern void sfTexture_destroy(IntPtr texture); - [DllImport(CSFML.Graphics, CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] - private static extern bool sfTexture_resize(IntPtr texture, Vector2u size); + [DllImport(CSFML.Graphics, CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] + private static extern bool sfTexture_resize(IntPtr texture, Vector2u size); - [DllImport(CSFML.Graphics, CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] - private static extern bool sfTexture_resizeSrgb(IntPtr texture, Vector2u size); + [DllImport(CSFML.Graphics, CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] + private static extern bool sfTexture_resizeSrgb(IntPtr texture, Vector2u size); - [DllImport(CSFML.Graphics, CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] - private static extern Vector2u sfTexture_getSize(IntPtr texture); + [DllImport(CSFML.Graphics, CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] + private static extern Vector2u sfTexture_getSize(IntPtr texture); - [DllImport(CSFML.Graphics, CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] - private static extern IntPtr sfTexture_copyToImage(IntPtr texture); + [DllImport(CSFML.Graphics, CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] + private static extern IntPtr sfTexture_copyToImage(IntPtr texture); - [DllImport(CSFML.Graphics, CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] - private static extern unsafe void sfTexture_updateFromPixels(IntPtr texture, byte* pixels, Vector2u size, Vector2u offset); + [DllImport(CSFML.Graphics, CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] + private static extern unsafe void sfTexture_updateFromPixels(IntPtr texture, byte* pixels, Vector2u size, Vector2u offset); - [DllImport(CSFML.Graphics, CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] - private static extern void sfTexture_updateFromTexture(IntPtr cPointer, IntPtr texture, Vector2u offset); + [DllImport(CSFML.Graphics, CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] + private static extern void sfTexture_updateFromTexture(IntPtr cPointer, IntPtr texture, Vector2u offset); - [DllImport(CSFML.Graphics, CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] - private static extern void sfTexture_updateFromImage(IntPtr texture, IntPtr image, Vector2u offset); + [DllImport(CSFML.Graphics, CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] + private static extern void sfTexture_updateFromImage(IntPtr texture, IntPtr image, Vector2u offset); - [DllImport(CSFML.Graphics, CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] - private static extern void sfTexture_updateFromWindow(IntPtr texture, IntPtr window, Vector2u offset); + [DllImport(CSFML.Graphics, CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] + private static extern void sfTexture_updateFromWindow(IntPtr texture, IntPtr window, Vector2u offset); - [DllImport(CSFML.Graphics, CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] - private static extern void sfTexture_updateFromRenderWindow(IntPtr texture, IntPtr renderWindow, Vector2u offset); + [DllImport(CSFML.Graphics, CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] + private static extern void sfTexture_updateFromRenderWindow(IntPtr texture, IntPtr renderWindow, Vector2u offset); - [DllImport(CSFML.Graphics, CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] - private static extern void sfTexture_bind(IntPtr texture, CoordinateType type); + [DllImport(CSFML.Graphics, CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] + private static extern void sfTexture_bind(IntPtr texture, CoordinateType type); - [DllImport(CSFML.Graphics, CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] - private static extern void sfTexture_setSmooth(IntPtr texture, bool smooth); + [DllImport(CSFML.Graphics, CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] + private static extern void sfTexture_setSmooth(IntPtr texture, bool smooth); - [DllImport(CSFML.Graphics, CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] - [return: MarshalAs(UnmanagedType.I1)] - private static extern bool sfTexture_isSmooth(IntPtr texture); + [DllImport(CSFML.Graphics, CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] + [return: MarshalAs(UnmanagedType.I1)] + private static extern bool sfTexture_isSmooth(IntPtr texture); - [DllImport(CSFML.Graphics, CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] - [return: MarshalAs(UnmanagedType.I1)] - private static extern bool sfTexture_isSrgb(IntPtr texture); + [DllImport(CSFML.Graphics, CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] + [return: MarshalAs(UnmanagedType.I1)] + private static extern bool sfTexture_isSrgb(IntPtr texture); - [DllImport(CSFML.Graphics, CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] - private static extern void sfTexture_setRepeated(IntPtr texture, bool repeated); + [DllImport(CSFML.Graphics, CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] + private static extern void sfTexture_setRepeated(IntPtr texture, bool repeated); - [DllImport(CSFML.Graphics, CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] - [return: MarshalAs(UnmanagedType.I1)] - private static extern bool sfTexture_isRepeated(IntPtr texture); + [DllImport(CSFML.Graphics, CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] + [return: MarshalAs(UnmanagedType.I1)] + private static extern bool sfTexture_isRepeated(IntPtr texture); - [DllImport(CSFML.Graphics, CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] - [return: MarshalAs(UnmanagedType.I1)] - private static extern bool sfTexture_generateMipmap(IntPtr texture); + [DllImport(CSFML.Graphics, CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] + [return: MarshalAs(UnmanagedType.I1)] + private static extern bool sfTexture_generateMipmap(IntPtr texture); - [DllImport(CSFML.Graphics, CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] - private static extern void sfTexture_swap(IntPtr cPointer, IntPtr right); + [DllImport(CSFML.Graphics, CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] + private static extern void sfTexture_swap(IntPtr cPointer, IntPtr right); - [DllImport(CSFML.Graphics, CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] - private static extern uint sfTexture_getNativeHandle(IntPtr shader); + [DllImport(CSFML.Graphics, CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] + private static extern uint sfTexture_getNativeHandle(IntPtr shader); - [DllImport(CSFML.Graphics, CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] - private static extern uint sfTexture_getMaximumSize(); - #endregion - } + [DllImport(CSFML.Graphics, CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] + private static extern uint sfTexture_getMaximumSize(); + #endregion } diff --git a/src/SFML.Graphics/Transform.cs b/src/SFML.Graphics/Transform.cs index 8ba54836..5b63c1f0 100644 --- a/src/SFML.Graphics/Transform.cs +++ b/src/SFML.Graphics/Transform.cs @@ -4,262 +4,261 @@ // TODO REIMPLEMENT WITH 4x4 MATRIX -namespace SFML.Graphics +namespace SFML.Graphics; + +//////////////////////////////////////////////////////////// +/// +/// Define a 3x3 transform matrix +/// +//////////////////////////////////////////////////////////// +[StructLayout(LayoutKind.Sequential)] +public struct Transform { //////////////////////////////////////////////////////////// /// - /// Define a 3x3 transform matrix + /// Construct a transform from a 3x3 matrix /// + /// Element (0, 0) of the matrix + /// Element (0, 1) of the matrix + /// Element (0, 2) of the matrix + /// Element (1, 0) of the matrix + /// Element (1, 1) of the matrix + /// Element (1, 2) of the matrix + /// Element (2, 0) of the matrix + /// Element (2, 1) of the matrix + /// Element (2, 2) of the matrix //////////////////////////////////////////////////////////// - [StructLayout(LayoutKind.Sequential)] - public struct Transform + public Transform(float a00, float a01, float a02, + float a10, float a11, float a12, + float a20, float a21, float a22) { - //////////////////////////////////////////////////////////// - /// - /// Construct a transform from a 3x3 matrix - /// - /// Element (0, 0) of the matrix - /// Element (0, 1) of the matrix - /// Element (0, 2) of the matrix - /// Element (1, 0) of the matrix - /// Element (1, 1) of the matrix - /// Element (1, 2) of the matrix - /// Element (2, 0) of the matrix - /// Element (2, 1) of the matrix - /// Element (2, 2) of the matrix - //////////////////////////////////////////////////////////// - public Transform(float a00, float a01, float a02, - float a10, float a11, float a12, - float a20, float a21, float a22) - { - M00 = a00; - M01 = a01; - M02 = a02; - M10 = a10; - M11 = a11; - M12 = a12; - M20 = a20; - M21 = a21; - M22 = a22; - } + M00 = a00; + M01 = a01; + M02 = a02; + M10 = a10; + M11 = a11; + M12 = a12; + M20 = a20; + M21 = a21; + M22 = a22; + } - //////////////////////////////////////////////////////////// - /// - /// Return the inverse of the transform. - /// - /// If the inverse cannot be computed, an identity transform - /// is returned. - /// - /// A new transform which is the inverse of self - //////////////////////////////////////////////////////////// - public Transform GetInverse() => sfTransform_getInverse(ref this); + //////////////////////////////////////////////////////////// + /// + /// Return the inverse of the transform. + /// + /// If the inverse cannot be computed, an identity transform + /// is returned. + /// + /// A new transform which is the inverse of self + //////////////////////////////////////////////////////////// + public Transform GetInverse() => sfTransform_getInverse(ref this); - //////////////////////////////////////////////////////////// - /// - /// Transform a 2D point. - /// - /// Point to transform - /// Transformed point - //////////////////////////////////////////////////////////// - public Vector2f TransformPoint(Vector2f point) => sfTransform_transformPoint(ref this, point); + //////////////////////////////////////////////////////////// + /// + /// Transform a 2D point. + /// + /// Point to transform + /// Transformed point + //////////////////////////////////////////////////////////// + public Vector2f TransformPoint(Vector2f point) => sfTransform_transformPoint(ref this, point); - //////////////////////////////////////////////////////////// - /// - /// 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. - /// - /// Rectangle to transform - /// Transformed rectangle - //////////////////////////////////////////////////////////// - public FloatRect TransformRect(FloatRect rectangle) => sfTransform_transformRect(ref this, rectangle); + //////////////////////////////////////////////////////////// + /// + /// 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. + /// + /// Rectangle to transform + /// Transformed rectangle + //////////////////////////////////////////////////////////// + public FloatRect TransformRect(FloatRect rectangle) => sfTransform_transformRect(ref this, rectangle); - //////////////////////////////////////////////////////////// - /// - /// Combine the current transform with another one. - /// - /// The result is a transform that is equivalent to applying - /// this followed by transform. Mathematically, it is - /// equivalent to a matrix multiplication. - /// - /// Transform to combine to this transform - //////////////////////////////////////////////////////////// - public void Combine(Transform transform) => sfTransform_combine(ref this, ref transform); + //////////////////////////////////////////////////////////// + /// + /// Combine the current transform with another one. + /// + /// The result is a transform that is equivalent to applying + /// this followed by transform. Mathematically, it is + /// equivalent to a matrix multiplication. + /// + /// Transform to combine to this transform + //////////////////////////////////////////////////////////// + public void Combine(Transform transform) => sfTransform_combine(ref this, ref transform); - //////////////////////////////////////////////////////////// - /// - /// Combine the current transform with a translation. - /// - /// Translation offset to apply - //////////////////////////////////////////////////////////// - public void Translate(Vector2f offset) => sfTransform_translate(ref this, offset); + //////////////////////////////////////////////////////////// + /// + /// Combine the current transform with a translation. + /// + /// Translation offset to apply + //////////////////////////////////////////////////////////// + public void Translate(Vector2f offset) => sfTransform_translate(ref this, offset); - //////////////////////////////////////////////////////////// - /// - /// Combine the current transform with a rotation. - /// - /// Rotation angle - //////////////////////////////////////////////////////////// - public void Rotate(Angle angle) => sfTransform_rotate(ref this, angle.Degrees); + //////////////////////////////////////////////////////////// + /// + /// Combine the current transform with a rotation. + /// + /// Rotation angle + //////////////////////////////////////////////////////////// + public void Rotate(Angle angle) => sfTransform_rotate(ref this, angle.Degrees); - //////////////////////////////////////////////////////////// - /// - /// 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). - /// - /// Rotation angle - /// Center of rotation - //////////////////////////////////////////////////////////// - public void Rotate(Angle angle, Vector2f center) => sfTransform_rotateWithCenter(ref this, angle.Degrees, center); + //////////////////////////////////////////////////////////// + /// + /// 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). + /// + /// Rotation angle + /// Center of rotation + //////////////////////////////////////////////////////////// + public void Rotate(Angle angle, Vector2f center) => sfTransform_rotateWithCenter(ref this, angle.Degrees, center); - //////////////////////////////////////////////////////////// - /// - /// Combine the current transform with a scaling. - /// - /// Scaling factors - //////////////////////////////////////////////////////////// - public void Scale(Vector2f factors) => sfTransform_scale(ref this, factors); + //////////////////////////////////////////////////////////// + /// + /// Combine the current transform with a scaling. + /// + /// Scaling factors + //////////////////////////////////////////////////////////// + public void Scale(Vector2f factors) => sfTransform_scale(ref this, factors); - //////////////////////////////////////////////////////////// - /// - /// 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). - /// - /// Scaling factors - /// Center of scaling - //////////////////////////////////////////////////////////// - public void Scale(Vector2f factors, Vector2f center) => sfTransform_scaleWithCenter(ref this, factors, center); + //////////////////////////////////////////////////////////// + /// + /// 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). + /// + /// Scaling factors + /// Center of scaling + //////////////////////////////////////////////////////////// + public void Scale(Vector2f factors, Vector2f center) => sfTransform_scaleWithCenter(ref this, factors, center); - //////////////////////////////////////////////////////////// - /// - /// Compare Transform and object and checks if they are equal - /// - /// Object to check - /// Object and transform are equal - //////////////////////////////////////////////////////////// - public override bool Equals(object obj) => (obj is Transform transform) && Equals(transform); + //////////////////////////////////////////////////////////// + /// + /// Compare Transform and object and checks if they are equal + /// + /// Object to check + /// Object and transform are equal + //////////////////////////////////////////////////////////// + public override bool Equals(object obj) => obj is Transform transform && Equals(transform); - //////////////////////////////////////////////////////////// - /// - /// Compare two transforms for equality - /// - /// Performs an element-wise comparison of the elements of this - /// transform with the elements of the right transform. - /// - /// Transform to check - /// Transforms are equal - //////////////////////////////////////////////////////////// - public bool Equals(Transform transform) => sfTransform_equal(ref this, ref transform); + //////////////////////////////////////////////////////////// + /// + /// Compare two transforms for equality + /// + /// Performs an element-wise comparison of the elements of this + /// transform with the elements of the right transform. + /// + /// Transform to check + /// Transforms are equal + //////////////////////////////////////////////////////////// + public bool Equals(Transform transform) => sfTransform_equal(ref this, ref transform); - //////////////////////////////////////////////////////////// - /// - /// Generates a hash code by XORing together the internal 3x3 matrix. - /// - /// XOR'd Hash of floats contained. - //////////////////////////////////////////////////////////// - public override int GetHashCode() - { - var hash0 = M00.GetHashCode() ^ M01.GetHashCode() ^ M02.GetHashCode(); - var hash1 = M10.GetHashCode() ^ M11.GetHashCode() ^ M12.GetHashCode(); - var hash2 = M20.GetHashCode() ^ M21.GetHashCode() ^ M22.GetHashCode(); - return hash0 ^ hash1 ^ hash2; - } + //////////////////////////////////////////////////////////// + /// + /// Generates a hash code by XORing together the internal 3x3 matrix. + /// + /// XOR'd Hash of floats contained. + //////////////////////////////////////////////////////////// + public override int GetHashCode() + { + var hash0 = M00.GetHashCode() ^ M01.GetHashCode() ^ M02.GetHashCode(); + var hash1 = M10.GetHashCode() ^ M11.GetHashCode() ^ M12.GetHashCode(); + var hash2 = M20.GetHashCode() ^ M21.GetHashCode() ^ M22.GetHashCode(); + return hash0 ^ hash1 ^ hash2; + } - //////////////////////////////////////////////////////////// - /// - /// Overload of binary operator * to combine two transforms. - /// This call is equivalent to calling new Transform(left).Combine(right). - /// - /// Left operand (the first transform) - /// Right operand (the second transform) - /// New combined transform - //////////////////////////////////////////////////////////// - public static Transform operator *(Transform left, Transform right) - { - left.Combine(right); - return left; - } + //////////////////////////////////////////////////////////// + /// + /// Overload of binary operator * to combine two transforms. + /// This call is equivalent to calling new Transform(left).Combine(right). + /// + /// Left operand (the first transform) + /// Right operand (the second transform) + /// New combined transform + //////////////////////////////////////////////////////////// + public static Transform operator *(Transform left, Transform right) + { + left.Combine(right); + return left; + } - //////////////////////////////////////////////////////////// - /// - /// Overload of binary operator * to transform a point. - /// This call is equivalent to calling left.TransformPoint(right). - /// - /// Left operand (the transform) - /// Right operand (the point to transform) - /// New transformed point - //////////////////////////////////////////////////////////// - public static Vector2f operator *(Transform left, Vector2f right) => left.TransformPoint(right); + //////////////////////////////////////////////////////////// + /// + /// Overload of binary operator * to transform a point. + /// This call is equivalent to calling left.TransformPoint(right). + /// + /// Left operand (the transform) + /// Right operand (the point to transform) + /// New transformed point + //////////////////////////////////////////////////////////// + public static Vector2f operator *(Transform left, Vector2f right) => left.TransformPoint(right); - //////////////////////////////////////////////////////////// - /// The identity transform (does nothing) - //////////////////////////////////////////////////////////// - public static Transform Identity => new Transform(1, 0, 0, - 0, 1, 0, - 0, 0, 1); + //////////////////////////////////////////////////////////// + /// The identity transform (does nothing) + //////////////////////////////////////////////////////////// + public static Transform Identity => new(1, 0, 0, + 0, 1, 0, + 0, 0, 1); - //////////////////////////////////////////////////////////// - /// - /// Provide a string describing the object - /// - /// String description of the object - //////////////////////////////////////////////////////////// - public override string ToString() => string.Format("[Transform]" + - " Matrix(" + - "{0}, {1}, {2}," + - "{3}, {4}, {5}," + - "{6}, {7}, {8}, )", - M00, M01, M02, - M10, M11, M12, - M20, M21, M22); + //////////////////////////////////////////////////////////// + /// + /// Provide a string describing the object + /// + /// String description of the object + //////////////////////////////////////////////////////////// + public override readonly string ToString() => string.Format("[Transform]" + + " Matrix(" + + "{0}, {1}, {2}," + + "{3}, {4}, {5}," + + "{6}, {7}, {8}, )", + M00, M01, M02, + M10, M11, M12, + M20, M21, M22); - internal float M00, M01, M02; - internal float M10, M11, M12; - internal float M20, M21, M22; + internal float M00, M01, M02; + internal float M10, M11, M12; + internal float M20, M21, M22; - #region Imports - [DllImport(CSFML.Graphics, CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] - private static extern Transform sfTransform_getInverse(ref Transform transform); + #region Imports + [DllImport(CSFML.Graphics, CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] + private static extern Transform sfTransform_getInverse(ref Transform transform); - [DllImport(CSFML.Graphics, CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] - private static extern Vector2f sfTransform_transformPoint(ref Transform transform, Vector2f point); + [DllImport(CSFML.Graphics, CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] + private static extern Vector2f sfTransform_transformPoint(ref Transform transform, Vector2f point); - [DllImport(CSFML.Graphics, CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] - private static extern FloatRect sfTransform_transformRect(ref Transform transform, FloatRect rectangle); + [DllImport(CSFML.Graphics, CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] + private static extern FloatRect sfTransform_transformRect(ref Transform transform, FloatRect rectangle); - [DllImport(CSFML.Graphics, CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] - private static extern void sfTransform_combine(ref Transform transform, ref Transform other); + [DllImport(CSFML.Graphics, CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] + private static extern void sfTransform_combine(ref Transform transform, ref Transform other); - [DllImport(CSFML.Graphics, CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] - private static extern void sfTransform_translate(ref Transform transform, Vector2f offset); + [DllImport(CSFML.Graphics, CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] + private static extern void sfTransform_translate(ref Transform transform, Vector2f offset); - [DllImport(CSFML.Graphics, CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] - private static extern void sfTransform_rotate(ref Transform transform, float angle); + [DllImport(CSFML.Graphics, CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] + private static extern void sfTransform_rotate(ref Transform transform, float angle); - [DllImport(CSFML.Graphics, CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] - private static extern void sfTransform_rotateWithCenter(ref Transform transform, float angle, Vector2f center); + [DllImport(CSFML.Graphics, CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] + private static extern void sfTransform_rotateWithCenter(ref Transform transform, float angle, Vector2f center); - [DllImport(CSFML.Graphics, CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] - private static extern void sfTransform_scale(ref Transform transform, Vector2f scale); + [DllImport(CSFML.Graphics, CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] + private static extern void sfTransform_scale(ref Transform transform, Vector2f scale); - [DllImport(CSFML.Graphics, CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] - private static extern void sfTransform_scaleWithCenter(ref Transform transform, Vector2f scale, Vector2f center); + [DllImport(CSFML.Graphics, CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] + private static extern void sfTransform_scaleWithCenter(ref Transform transform, Vector2f scale, Vector2f center); - [DllImport(CSFML.Graphics, CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] - [return: MarshalAs(UnmanagedType.I1)] - private static extern bool sfTransform_equal(ref Transform left, ref Transform right); - #endregion - } + [DllImport(CSFML.Graphics, CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] + [return: MarshalAs(UnmanagedType.I1)] + private static extern bool sfTransform_equal(ref Transform left, ref Transform right); + #endregion } diff --git a/src/SFML.Graphics/Transformable.cs b/src/SFML.Graphics/Transformable.cs index 52510a3a..3ee2d889 100644 --- a/src/SFML.Graphics/Transformable.cs +++ b/src/SFML.Graphics/Transformable.cs @@ -1,200 +1,199 @@ using System; using SFML.System; -namespace SFML.Graphics +namespace SFML.Graphics; + +//////////////////////////////////////////////////////////// +/// +/// Decomposed transform defined by a position, a rotation and a scale +/// +/// +/// A note on coordinates and undistorted rendering: +/// 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 SFML.Graphics.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 +/// +//////////////////////////////////////////////////////////// +public class Transformable : ObjectBase { //////////////////////////////////////////////////////////// /// - /// Decomposed transform defined by a position, a rotation and a scale + /// Default constructor /// - /// - /// A note on coordinates and undistorted rendering: - /// 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 SFML.Graphics.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 - /// - //////////////////////////////////////////////////////////// - public class Transformable : ObjectBase + //////////////////////////////////////////////////////////// + public Transformable() : + base(IntPtr.Zero) { - //////////////////////////////////////////////////////////// - /// - /// Default constructor - /// - //////////////////////////////////////////////////////////// - public Transformable() : - base(IntPtr.Zero) - { - } + } - //////////////////////////////////////////////////////////// - /// - /// Construct the transformable from another transformable - /// - /// Transformable to copy - //////////////////////////////////////////////////////////// - public Transformable(Transformable transformable) : - base(IntPtr.Zero) - { - Origin = transformable.Origin; - Position = transformable.Position; - Rotation = transformable.Rotation; - Scale = transformable.Scale; - } + //////////////////////////////////////////////////////////// + /// + /// Construct the transformable from another transformable + /// + /// Transformable to copy + //////////////////////////////////////////////////////////// + public Transformable(Transformable transformable) : + base(IntPtr.Zero) + { + Origin = transformable.Origin; + Position = transformable.Position; + Rotation = transformable.Rotation; + Scale = transformable.Scale; + } - //////////////////////////////////////////////////////////// - /// - /// Position of the object - /// - //////////////////////////////////////////////////////////// - public Vector2f Position + //////////////////////////////////////////////////////////// + /// + /// Position of the object + /// + //////////////////////////////////////////////////////////// + public Vector2f Position + { + get => _position; + set { - get => _position; - set - { - _position = value; - _transformNeedUpdate = true; - _inverseNeedUpdate = true; - } + _position = value; + _transformNeedUpdate = true; + _inverseNeedUpdate = true; } + } - //////////////////////////////////////////////////////////// - /// - /// Rotation of the object - /// - //////////////////////////////////////////////////////////// - public float Rotation + //////////////////////////////////////////////////////////// + /// + /// Rotation of the object + /// + //////////////////////////////////////////////////////////// + public float Rotation + { + get => _rotation; + set { - get => _rotation; - set - { - _rotation = value; - _transformNeedUpdate = true; - _inverseNeedUpdate = true; - } + _rotation = value; + _transformNeedUpdate = true; + _inverseNeedUpdate = true; } + } - //////////////////////////////////////////////////////////// - /// - /// Scale of the object - /// - //////////////////////////////////////////////////////////// - public Vector2f Scale + //////////////////////////////////////////////////////////// + /// + /// Scale of the object + /// + //////////////////////////////////////////////////////////// + public Vector2f Scale + { + get => _scale; + set { - get => _scale; - set - { - _scale = value; - _transformNeedUpdate = true; - _inverseNeedUpdate = true; - } + _scale = value; + _transformNeedUpdate = true; + _inverseNeedUpdate = true; } + } - //////////////////////////////////////////////////////////// - /// - /// 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). - /// - //////////////////////////////////////////////////////////// - public Vector2f Origin + //////////////////////////////////////////////////////////// + /// + /// 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). + /// + //////////////////////////////////////////////////////////// + public Vector2f Origin + { + get => _origin; + set { - get => _origin; - set - { - _origin = value; - _transformNeedUpdate = true; - _inverseNeedUpdate = true; - } + _origin = value; + _transformNeedUpdate = true; + _inverseNeedUpdate = true; } + } - //////////////////////////////////////////////////////////// - /// - /// The combined transform of the object - /// - //////////////////////////////////////////////////////////// - public Transform Transform + //////////////////////////////////////////////////////////// + /// + /// The combined transform of the object + /// + //////////////////////////////////////////////////////////// + public Transform Transform + { + get { - get + if (_transformNeedUpdate) { - if (_transformNeedUpdate) - { - _transformNeedUpdate = false; + _transformNeedUpdate = false; - var angle = -_rotation * 3.141592654F / 180.0F; - var cosine = (float)Math.Cos(angle); - var sine = (float)Math.Sin(angle); - var sxc = _scale.X * cosine; - var syc = _scale.Y * cosine; - var sxs = _scale.X * sine; - var sys = _scale.Y * sine; - var tx = (-_origin.X * sxc) - (_origin.Y * sys) + _position.X; - var ty = (_origin.X * sxs) - (_origin.Y * syc) + _position.Y; + var angle = -_rotation * 3.141592654F / 180.0F; + var cosine = (float)Math.Cos(angle); + var sine = (float)Math.Sin(angle); + var sxc = _scale.X * cosine; + var syc = _scale.Y * cosine; + var sxs = _scale.X * sine; + var sys = _scale.Y * sine; + var tx = (-_origin.X * sxc) - (_origin.Y * sys) + _position.X; + var ty = (_origin.X * sxs) - (_origin.Y * syc) + _position.Y; - _transform = new Transform(sxc, sys, tx, - -sxs, syc, ty, - 0.0F, 0.0F, 1.0F); - } - return _transform; + _transform = new Transform(sxc, sys, tx, + -sxs, syc, ty, + 0.0F, 0.0F, 1.0F); } + return _transform; } + } - //////////////////////////////////////////////////////////// - /// - /// The combined transform of the object - /// - //////////////////////////////////////////////////////////// - public Transform InverseTransform + //////////////////////////////////////////////////////////// + /// + /// The combined transform of the object + /// + //////////////////////////////////////////////////////////// + public Transform InverseTransform + { + get { - get + if (_inverseNeedUpdate) { - if (_inverseNeedUpdate) - { - _inverseTransform = Transform.GetInverse(); - _inverseNeedUpdate = false; - } - return _inverseTransform; + _inverseTransform = Transform.GetInverse(); + _inverseNeedUpdate = false; } + return _inverseTransform; } + } - //////////////////////////////////////////////////////////// - /// - /// Construct the object from its internal C pointer - /// - /// Pointer to the object in the C library - //////////////////////////////////////////////////////////// - protected Transformable(IntPtr cPointer) : - base(cPointer) - { - } - - //////////////////////////////////////////////////////////// - /// - /// Handle the destruction of the object - /// - /// Is the GC disposing the object, or is it an explicit call ? - //////////////////////////////////////////////////////////// - protected override void Destroy(bool disposing) - { - // Does nothing, this instance is either pure C# (if created by the user) - // or not the final object (if used as a base for a drawable class) - } + //////////////////////////////////////////////////////////// + /// + /// Construct the object from its internal C pointer + /// + /// Pointer to the object in the C library + //////////////////////////////////////////////////////////// + protected Transformable(IntPtr cPointer) : + base(cPointer) + { + } - private Vector2f _origin = new Vector2f(0, 0); - private Vector2f _position = new Vector2f(0, 0); - private float _rotation; - private Vector2f _scale = new Vector2f(1, 1); - private Transform _transform; - private Transform _inverseTransform; - private bool _transformNeedUpdate = true; - private bool _inverseNeedUpdate = true; + //////////////////////////////////////////////////////////// + /// + /// Handle the destruction of the object + /// + /// Is the GC disposing the object, or is it an explicit call ? + //////////////////////////////////////////////////////////// + protected override void Destroy(bool disposing) + { + // Does nothing, this instance is either pure C# (if created by the user) + // or not the final object (if used as a base for a drawable class) } + + private Vector2f _origin = new(0, 0); + private Vector2f _position = new(0, 0); + private float _rotation; + private Vector2f _scale = new(1, 1); + private Transform _transform; + private Transform _inverseTransform; + private bool _transformNeedUpdate = true; + private bool _inverseNeedUpdate = true; } diff --git a/src/SFML.Graphics/Vertex.cs b/src/SFML.Graphics/Vertex.cs index 6ed013dc..f790c5bd 100644 --- a/src/SFML.Graphics/Vertex.cs +++ b/src/SFML.Graphics/Vertex.cs @@ -1,87 +1,86 @@ using System.Runtime.InteropServices; using SFML.System; -namespace SFML.Graphics +namespace SFML.Graphics; + +//////////////////////////////////////////////////////////// +/// +/// Define a point with color and texture coordinates +/// +//////////////////////////////////////////////////////////// +[StructLayout(LayoutKind.Sequential)] +public struct Vertex { //////////////////////////////////////////////////////////// /// - /// Define a point with color and texture coordinates + /// Construct the vertex from its position + /// The vertex color is white and texture coordinates are (0, 0). /// + /// Vertex position //////////////////////////////////////////////////////////// - [StructLayout(LayoutKind.Sequential)] - public struct Vertex + public Vertex(Vector2f position) : + this(position, Color.White, new Vector2f(0, 0)) { - //////////////////////////////////////////////////////////// - /// - /// Construct the vertex from its position - /// The vertex color is white and texture coordinates are (0, 0). - /// - /// Vertex position - //////////////////////////////////////////////////////////// - public Vertex(Vector2f position) : - this(position, Color.White, new Vector2f(0, 0)) - { - } + } - //////////////////////////////////////////////////////////// - /// - /// Construct the vertex from its position and color - /// The texture coordinates are (0, 0). - /// - /// Vertex position - /// Vertex color - //////////////////////////////////////////////////////////// - public Vertex(Vector2f position, Color color) : - this(position, color, new Vector2f(0, 0)) - { - } + //////////////////////////////////////////////////////////// + /// + /// Construct the vertex from its position and color + /// The texture coordinates are (0, 0). + /// + /// Vertex position + /// Vertex color + //////////////////////////////////////////////////////////// + public Vertex(Vector2f position, Color color) : + this(position, color, new Vector2f(0, 0)) + { + } - //////////////////////////////////////////////////////////// - /// - /// Construct the vertex from its position and texture coordinates - /// The vertex color is white. - /// - /// Vertex position - /// Vertex texture coordinates - //////////////////////////////////////////////////////////// - public Vertex(Vector2f position, Vector2f texCoords) : - this(position, Color.White, texCoords) - { - } + //////////////////////////////////////////////////////////// + /// + /// Construct the vertex from its position and texture coordinates + /// The vertex color is white. + /// + /// Vertex position + /// Vertex texture coordinates + //////////////////////////////////////////////////////////// + public Vertex(Vector2f position, Vector2f texCoords) : + this(position, Color.White, texCoords) + { + } - //////////////////////////////////////////////////////////// - /// - /// Construct the vertex from its position, color and texture coordinates - /// - /// Vertex position - /// Vertex color - /// Vertex texture coordinates - //////////////////////////////////////////////////////////// - public Vertex(Vector2f position, Color color, Vector2f texCoords) - { - Position = position; - Color = color; - TexCoords = texCoords; - } + //////////////////////////////////////////////////////////// + /// + /// Construct the vertex from its position, color and texture coordinates + /// + /// Vertex position + /// Vertex color + /// Vertex texture coordinates + //////////////////////////////////////////////////////////// + public Vertex(Vector2f position, Color color, Vector2f texCoords) + { + Position = position; + Color = color; + TexCoords = texCoords; + } - //////////////////////////////////////////////////////////// - /// - /// Provide a string describing the object - /// - /// String description of the object - //////////////////////////////////////////////////////////// - public override string ToString() => "[Vertex]" + - " Position(" + Position + ")" + - " Color(" + Color + ")" + - " TexCoords(" + TexCoords + ")"; + //////////////////////////////////////////////////////////// + /// + /// Provide a string describing the object + /// + /// String description of the object + //////////////////////////////////////////////////////////// + public override readonly string ToString() => "[Vertex]" + + " Position(" + Position + ")" + + " Color(" + Color + ")" + + " TexCoords(" + TexCoords + ")"; - /// 2D position of the vertex - public Vector2f Position; + /// 2D position of the vertex + public Vector2f Position; - /// Color of the vertex - public Color Color; + /// Color of the vertex + public Color Color; - /// Coordinates of the texture's pixel to map to the vertex - public Vector2f TexCoords; - } + /// Coordinates of the texture's pixel to map to the vertex + public Vector2f TexCoords; } diff --git a/src/SFML.Graphics/VertexArray.cs b/src/SFML.Graphics/VertexArray.cs index d47e62dd..e2019635 100644 --- a/src/SFML.Graphics/VertexArray.cs +++ b/src/SFML.Graphics/VertexArray.cs @@ -3,218 +3,217 @@ using System.Security; using SFML.System; -namespace SFML.Graphics +namespace SFML.Graphics; + +//////////////////////////////////////////////////////////// +/// +/// Define a set of one or more 2D primitives +/// +//////////////////////////////////////////////////////////// +public class VertexArray : ObjectBase, IDrawable { //////////////////////////////////////////////////////////// /// - /// Define a set of one or more 2D primitives + /// Default constructor /// //////////////////////////////////////////////////////////// - public class VertexArray : ObjectBase, IDrawable + public VertexArray() : + base(sfVertexArray_create()) { - //////////////////////////////////////////////////////////// - /// - /// Default constructor - /// - //////////////////////////////////////////////////////////// - public VertexArray() : - base(sfVertexArray_create()) - { - } + } - //////////////////////////////////////////////////////////// - /// - /// Construct the vertex array with a - /// - /// Type of primitives - //////////////////////////////////////////////////////////// - public VertexArray(PrimitiveType type) : - base(sfVertexArray_create()) => PrimitiveType = type; - - //////////////////////////////////////////////////////////// - /// - /// Construct the vertex array with a and an initial number of vertices - /// - /// Type of primitives - /// Initial number of vertices in the array - //////////////////////////////////////////////////////////// - public VertexArray(PrimitiveType type, uint vertexCount) : - base(sfVertexArray_create()) - { - PrimitiveType = type; - Resize(vertexCount); - } + //////////////////////////////////////////////////////////// + /// + /// Construct the vertex array with a + /// + /// Type of primitives + //////////////////////////////////////////////////////////// + public VertexArray(PrimitiveType type) : + base(sfVertexArray_create()) => PrimitiveType = type; - //////////////////////////////////////////////////////////// - /// - /// Construct the vertex array from another - /// - /// Transformable to copy - //////////////////////////////////////////////////////////// - public VertexArray(VertexArray copy) : - base(sfVertexArray_copy(copy.CPointer)) - { - } + //////////////////////////////////////////////////////////// + /// + /// Construct the vertex array with a and an initial number of vertices + /// + /// Type of primitives + /// Initial number of vertices in the array + //////////////////////////////////////////////////////////// + public VertexArray(PrimitiveType type, uint vertexCount) : + base(sfVertexArray_create()) + { + PrimitiveType = type; + Resize(vertexCount); + } - //////////////////////////////////////////////////////////// - /// - /// Total count - /// - //////////////////////////////////////////////////////////// - public uint VertexCount => (uint)sfVertexArray_getVertexCount(CPointer); - - //////////////////////////////////////////////////////////// - /// - /// Read-Write access to vertices by their index. - /// - /// - /// This function doesn't check index, it must be in range - /// [0, VertexCount - 1]. The behaviour is undefined - /// otherwise. See . - /// - /// Index of the vertex to get - /// Copy of the index-th vertex. - //////////////////////////////////////////////////////////// - public Vertex this[uint index] + //////////////////////////////////////////////////////////// + /// + /// Construct the vertex array from another + /// + /// Transformable to copy + //////////////////////////////////////////////////////////// + public VertexArray(VertexArray copy) : + base(sfVertexArray_copy(copy.CPointer)) + { + } + + //////////////////////////////////////////////////////////// + /// + /// Total count + /// + //////////////////////////////////////////////////////////// + public uint VertexCount => (uint)sfVertexArray_getVertexCount(CPointer); + + //////////////////////////////////////////////////////////// + /// + /// Read-Write access to vertices by their index. + /// + /// + /// This function doesn't check index, it must be in range + /// [0, VertexCount - 1]. The behaviour is undefined + /// otherwise. See . + /// + /// Index of the vertex to get + /// Copy of the index-th vertex. + //////////////////////////////////////////////////////////// + public Vertex this[uint index] + { + get { - get + unsafe { - unsafe - { - return *sfVertexArray_getVertex(CPointer, (UIntPtr)index); - } + return *sfVertexArray_getVertex(CPointer, (UIntPtr)index); } - set + } + set + { + unsafe { - unsafe - { - *sfVertexArray_getVertex(CPointer, (UIntPtr)index) = value; - } + *sfVertexArray_getVertex(CPointer, (UIntPtr)index) = value; } } + } + + //////////////////////////////////////////////////////////// + /// + /// Clear the vertex array + /// + //////////////////////////////////////////////////////////// + public void Clear() => sfVertexArray_clear(CPointer); + + //////////////////////////////////////////////////////////// + /// + /// Resize the vertex array + /// + /// + /// If is greater than the current size, the previous + /// vertices are kept and new (default-constructed) vertices are + /// added. + /// If is less than the current size, existing vertices + /// are removed from the array. + /// + /// New size of the array (number of vertices) + //////////////////////////////////////////////////////////// + public void Resize(uint vertexCount) => sfVertexArray_resize(CPointer, (UIntPtr)vertexCount); + + //////////////////////////////////////////////////////////// + /// + /// Add a to the array + /// + /// Vertex to add + //////////////////////////////////////////////////////////// + public void Append(Vertex vertex) => sfVertexArray_append(CPointer, vertex); - //////////////////////////////////////////////////////////// - /// - /// Clear the vertex array - /// - //////////////////////////////////////////////////////////// - public void Clear() => sfVertexArray_clear(CPointer); - - //////////////////////////////////////////////////////////// - /// - /// Resize the vertex array - /// - /// - /// If is greater than the current size, the previous - /// vertices are kept and new (default-constructed) vertices are - /// added. - /// If is less than the current size, existing vertices - /// are removed from the array. - /// - /// New size of the array (number of vertices) - //////////////////////////////////////////////////////////// - public void Resize(uint vertexCount) => sfVertexArray_resize(CPointer, (UIntPtr)vertexCount); - - //////////////////////////////////////////////////////////// - /// - /// Add a to the array - /// - /// Vertex to add - //////////////////////////////////////////////////////////// - public void Append(Vertex vertex) => sfVertexArray_append(CPointer, vertex); - - //////////////////////////////////////////////////////////// - /// - /// Type of primitives to draw - /// - /// - /// See - /// - //////////////////////////////////////////////////////////// - public PrimitiveType PrimitiveType + //////////////////////////////////////////////////////////// + /// + /// Type of primitives to draw + /// + /// + /// See + /// + //////////////////////////////////////////////////////////// + public PrimitiveType PrimitiveType + { + get => sfVertexArray_getPrimitiveType(CPointer); + set => sfVertexArray_setPrimitiveType(CPointer, value); + } + + //////////////////////////////////////////////////////////// + /// + /// Compute the bounding rectangle of the vertex array. + /// + /// + /// Contains the axis-aligned that contains all the vertices of the array. + /// + //////////////////////////////////////////////////////////// + public FloatRect Bounds => sfVertexArray_getBounds(CPointer); + + //////////////////////////////////////////////////////////// + /// + /// Draw the vertex array to a + /// + /// Render target to draw to + /// Current render states + //////////////////////////////////////////////////////////// + public void Draw(IRenderTarget target, RenderStates states) + { + var marshaledStates = states.Marshal(); + + if (target is RenderWindow window) { - get => sfVertexArray_getPrimitiveType(CPointer); - set => sfVertexArray_setPrimitiveType(CPointer, value); + sfRenderWindow_drawVertexArray(window.CPointer, CPointer, ref marshaledStates); } - - //////////////////////////////////////////////////////////// - /// - /// Compute the bounding rectangle of the vertex array. - /// - /// - /// Contains the axis-aligned that contains all the vertices of the array. - /// - //////////////////////////////////////////////////////////// - public FloatRect Bounds => sfVertexArray_getBounds(CPointer); - - //////////////////////////////////////////////////////////// - /// - /// Draw the vertex array to a - /// - /// Render target to draw to - /// Current render states - //////////////////////////////////////////////////////////// - public void Draw(IRenderTarget target, RenderStates states) + else if (target is RenderTexture texture) { - var marshaledStates = states.Marshal(); - - if (target is RenderWindow window) - { - sfRenderWindow_drawVertexArray(window.CPointer, CPointer, ref marshaledStates); - } - else if (target is RenderTexture texture) - { - sfRenderTexture_drawVertexArray(texture.CPointer, CPointer, ref marshaledStates); - } + sfRenderTexture_drawVertexArray(texture.CPointer, CPointer, ref marshaledStates); } + } - //////////////////////////////////////////////////////////// - /// - /// Handle the destruction of the object - /// - /// Is the GC disposing the object, or is it an explicit call ? - //////////////////////////////////////////////////////////// - protected override void Destroy(bool disposing) => sfVertexArray_destroy(CPointer); + //////////////////////////////////////////////////////////// + /// + /// Handle the destruction of the object + /// + /// Is the GC disposing the object, or is it an explicit call ? + //////////////////////////////////////////////////////////// + protected override void Destroy(bool disposing) => sfVertexArray_destroy(CPointer); - #region Imports - [DllImport(CSFML.Graphics, CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] - private static extern IntPtr sfVertexArray_create(); + #region Imports + [DllImport(CSFML.Graphics, CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] + private static extern IntPtr sfVertexArray_create(); - [DllImport(CSFML.Graphics, CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] - private static extern IntPtr sfVertexArray_copy(IntPtr cPointer); + [DllImport(CSFML.Graphics, CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] + private static extern IntPtr sfVertexArray_copy(IntPtr cPointer); - [DllImport(CSFML.Graphics, CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] - private static extern void sfVertexArray_destroy(IntPtr cPointer); + [DllImport(CSFML.Graphics, CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] + private static extern void sfVertexArray_destroy(IntPtr cPointer); - [DllImport(CSFML.Graphics, CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] - private static extern UIntPtr sfVertexArray_getVertexCount(IntPtr cPointer); + [DllImport(CSFML.Graphics, CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] + private static extern UIntPtr sfVertexArray_getVertexCount(IntPtr cPointer); - [DllImport(CSFML.Graphics, CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] - private static extern unsafe Vertex* sfVertexArray_getVertex(IntPtr cPointer, UIntPtr index); + [DllImport(CSFML.Graphics, CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] + private static extern unsafe Vertex* sfVertexArray_getVertex(IntPtr cPointer, UIntPtr index); - [DllImport(CSFML.Graphics, CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] - private static extern void sfVertexArray_clear(IntPtr cPointer); + [DllImport(CSFML.Graphics, CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] + private static extern void sfVertexArray_clear(IntPtr cPointer); - [DllImport(CSFML.Graphics, CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] - private static extern void sfVertexArray_resize(IntPtr cPointer, UIntPtr vertexCount); + [DllImport(CSFML.Graphics, CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] + private static extern void sfVertexArray_resize(IntPtr cPointer, UIntPtr vertexCount); - [DllImport(CSFML.Graphics, CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] - private static extern void sfVertexArray_append(IntPtr cPointer, Vertex vertex); + [DllImport(CSFML.Graphics, CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] + private static extern void sfVertexArray_append(IntPtr cPointer, Vertex vertex); - [DllImport(CSFML.Graphics, CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] - private static extern void sfVertexArray_setPrimitiveType(IntPtr cPointer, PrimitiveType type); + [DllImport(CSFML.Graphics, CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] + private static extern void sfVertexArray_setPrimitiveType(IntPtr cPointer, PrimitiveType type); - [DllImport(CSFML.Graphics, CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] - private static extern PrimitiveType sfVertexArray_getPrimitiveType(IntPtr cPointer); + [DllImport(CSFML.Graphics, CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] + private static extern PrimitiveType sfVertexArray_getPrimitiveType(IntPtr cPointer); - [DllImport(CSFML.Graphics, CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] - private static extern FloatRect sfVertexArray_getBounds(IntPtr cPointer); + [DllImport(CSFML.Graphics, CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] + private static extern FloatRect sfVertexArray_getBounds(IntPtr cPointer); - [DllImport(CSFML.Graphics, CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] - private static extern void sfRenderWindow_drawVertexArray(IntPtr cPointer, IntPtr vertexArray, ref RenderStates.MarshalData states); + [DllImport(CSFML.Graphics, CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] + private static extern void sfRenderWindow_drawVertexArray(IntPtr cPointer, IntPtr vertexArray, ref RenderStates.MarshalData states); - [DllImport(CSFML.Graphics, CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] - private static extern void sfRenderTexture_drawVertexArray(IntPtr cPointer, IntPtr vertexArray, ref RenderStates.MarshalData states); - #endregion - } + [DllImport(CSFML.Graphics, CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] + private static extern void sfRenderTexture_drawVertexArray(IntPtr cPointer, IntPtr vertexArray, ref RenderStates.MarshalData states); + #endregion } diff --git a/src/SFML.Graphics/VertexBuffer.cs b/src/SFML.Graphics/VertexBuffer.cs index 1047672e..c4b2c238 100644 --- a/src/SFML.Graphics/VertexBuffer.cs +++ b/src/SFML.Graphics/VertexBuffer.cs @@ -3,377 +3,376 @@ using System.Runtime.InteropServices; using System.Security; -namespace SFML.Graphics +namespace SFML.Graphics; + +//////////////////////////////////////////////////////////// +/// +/// Vertex buffer storage for one or more 2D primitives. +/// +/// VertexBuffer is a simple wrapper around a dynamic buffer of vertices and a primitives type. +/// +/// Unlike SFML.VertexArray, the vertex data is stored in graphics memory. +/// +//////////////////////////////////////////////////////////// +public class VertexBuffer : ObjectBase, IDrawable { //////////////////////////////////////////////////////////// /// - /// Vertex buffer storage for one or more 2D primitives. - /// - /// VertexBuffer is a simple wrapper around a dynamic buffer of vertices and a primitives type. - /// - /// Unlike SFML.VertexArray, the vertex data is stored in graphics memory. + /// Usage Specifiers /// + /// + /// If data is going to be updated once or more every frame, use . + /// If data is going to be set once and used for a long time without being modified, use . + /// For everything else, should be a good compromise. + /// //////////////////////////////////////////////////////////// - public class VertexBuffer : ObjectBase, IDrawable + public enum UsageSpecifier { - //////////////////////////////////////////////////////////// - /// - /// Usage Specifiers - /// - /// - /// If data is going to be updated once or more every frame, use . - /// If data is going to be set once and used for a long time without being modified, use . - /// For everything else, should be a good compromise. - /// - //////////////////////////////////////////////////////////// - public enum UsageSpecifier - { - /// Constantly changing data. - /// Use when the will be updated once or more every frame. - Stream, - /// Occasionally changing data. - /// Use when the will change infrequently. - Dynamic, - /// Rarely changing data. - /// Use when the will rarely of never be changed. - Static - } + /// Constantly changing data. + /// Use when the will be updated once or more every frame. + Stream, + /// Occasionally changing data. + /// Use when the will change infrequently. + Dynamic, + /// Rarely changing data. + /// Use when the will rarely of never be changed. + Static + } - //////////////////////////////////////////////////////////// - /// - /// Whether or not the system supports s - /// - /// - /// This function should always be called before using - /// the vertex buffer features. If it returns false, then - /// any attempt to use will fail. - /// - /////////////////////////////////////////////////////////// - public static bool Available => sfVertexBuffer_isAvailable(); - - //////////////////////////////////////////////////////////// - /// - /// Create a new with a specific - /// and - /// - /// - /// Creates the vertex buffer, allocating enough graphics - /// memory to hold vertices, and sets its - /// to primitiveType and to usageType. - /// - /// Amount of vertices - /// Type of primitives - /// Usage specifier - //////////////////////////////////////////////////////////// - public VertexBuffer(uint vertexCount, PrimitiveType primitiveType, UsageSpecifier usageType) - : base(sfVertexBuffer_create(vertexCount, primitiveType, usageType)) - { - } + //////////////////////////////////////////////////////////// + /// + /// Whether or not the system supports s + /// + /// + /// This function should always be called before using + /// the vertex buffer features. If it returns false, then + /// any attempt to use will fail. + /// + /////////////////////////////////////////////////////////// + public static bool Available => sfVertexBuffer_isAvailable(); - //////////////////////////////////////////////////////////// - /// - /// Construct the vertex buffer from another - /// - /// VertexBuffer to copy - //////////////////////////////////////////////////////////// - public VertexBuffer(VertexBuffer copy) - : base(sfVertexBuffer_copy(copy.CPointer)) - { - } + //////////////////////////////////////////////////////////// + /// + /// Create a new with a specific + /// and + /// + /// + /// Creates the vertex buffer, allocating enough graphics + /// memory to hold vertices, and sets its + /// to primitiveType and to usageType. + /// + /// Amount of vertices + /// Type of primitives + /// Usage specifier + //////////////////////////////////////////////////////////// + public VertexBuffer(uint vertexCount, PrimitiveType primitiveType, UsageSpecifier usageType) + : base(sfVertexBuffer_create(vertexCount, primitiveType, usageType)) + { + } - //////////////////////////////////////////////////////////// - /// - /// Total vertex count - /// - //////////////////////////////////////////////////////////// - public uint VertexCount => sfVertexBuffer_getVertexCount(CPointer); - - //////////////////////////////////////////////////////////// - /// - /// OpenGL handle of the vertex buffer or 0 if not yet created - /// - /// - /// You shouldn't need to use this property, unless you have - /// very specific stuff to implement that SFML doesn't support, - /// or implement a temporary workaround until a bug is fixed. - /// - //////////////////////////////////////////////////////////// - public uint NativeHandle => sfVertexBuffer_getNativeHandle(CPointer); - - //////////////////////////////////////////////////////////// - /// - /// The drawn by the - /// - //////////////////////////////////////////////////////////// - public PrimitiveType PrimitiveType - { - get => sfVertexBuffer_getPrimitiveType(CPointer); - set => sfVertexBuffer_setPrimitiveType(CPointer, value); - } + //////////////////////////////////////////////////////////// + /// + /// Construct the vertex buffer from another + /// + /// VertexBuffer to copy + //////////////////////////////////////////////////////////// + public VertexBuffer(VertexBuffer copy) + : base(sfVertexBuffer_copy(copy.CPointer)) + { + } - //////////////////////////////////////////////////////////// - /// - /// The for the - /// - //////////////////////////////////////////////////////////// - public UsageSpecifier Usage - { - get => sfVertexBuffer_getUsage(CPointer); - set => sfVertexBuffer_setUsage(CPointer, value); - } + //////////////////////////////////////////////////////////// + /// + /// Total vertex count + /// + //////////////////////////////////////////////////////////// + public uint VertexCount => sfVertexBuffer_getVertexCount(CPointer); + + //////////////////////////////////////////////////////////// + /// + /// OpenGL handle of the vertex buffer or 0 if not yet created + /// + /// + /// You shouldn't need to use this property, unless you have + /// very specific stuff to implement that SFML doesn't support, + /// or implement a temporary workaround until a bug is fixed. + /// + //////////////////////////////////////////////////////////// + public uint NativeHandle => sfVertexBuffer_getNativeHandle(CPointer); + + //////////////////////////////////////////////////////////// + /// + /// The drawn by the + /// + //////////////////////////////////////////////////////////// + public PrimitiveType PrimitiveType + { + get => sfVertexBuffer_getPrimitiveType(CPointer); + set => sfVertexBuffer_setPrimitiveType(CPointer, value); + } + + //////////////////////////////////////////////////////////// + /// + /// The for the + /// + //////////////////////////////////////////////////////////// + public UsageSpecifier Usage + { + get => sfVertexBuffer_getUsage(CPointer); + set => sfVertexBuffer_setUsage(CPointer, value); + } + + //////////////////////////////////////////////////////////// + /// + /// Bind a for rendering. + /// + /// + /// This function is not part of the graphics API. + /// It must not be used when drawing SFML entities. + /// It must be used only if you mix VertexBuffer with OpenGL code. + /// + /// The vertex buffer to bind; can be null to use no vertex buffer + //////////////////////////////////////////////////////////// + public static void Bind(VertexBuffer vertexBuffer) => sfVertexBuffer_bind(vertexBuffer?.CPointer ?? IntPtr.Zero); - //////////////////////////////////////////////////////////// - /// - /// Bind a for rendering. - /// - /// - /// This function is not part of the graphics API. - /// It must not be used when drawing SFML entities. - /// It must be used only if you mix VertexBuffer with OpenGL code. - /// - /// The vertex buffer to bind; can be null to use no vertex buffer - //////////////////////////////////////////////////////////// - public static void Bind(VertexBuffer vertexBuffer) => sfVertexBuffer_bind(vertexBuffer?.CPointer ?? IntPtr.Zero); - - //////////////////////////////////////////////////////////// - /// - /// Update the from a [] - /// - /// - /// - /// is specified as the number of vertices to skip - /// from the beginning of the buffer. - /// - /// - /// If is 0 and is equal to the size of - /// the currently created buffer, its whole contents are replaced. - /// - /// - /// If is 0 and is greater than the - /// size of the currently created buffer, a new buffer is created - /// containing the data. - /// - /// - /// If is 0 and is less than the size of - /// the currently created buffer, only the corresponding region - /// is updated. - /// - /// - /// If is NOT 0 and + - /// is greater than the size of the currently - /// created buffer, the update fails. - /// - /// - /// No additional checks are performed on the size of the . - /// Passing invalid arguments will lead to undefined behavior. - /// - /// - /// Array of vertices to copy from - /// Number of vertices to copy - /// Offset in the buffer to copy to - //////////////////////////////////////////////////////////// - public bool Update(Vertex[] vertices, uint vertexCount, uint offset) + //////////////////////////////////////////////////////////// + /// + /// Update the from a [] + /// + /// + /// + /// is specified as the number of vertices to skip + /// from the beginning of the buffer. + /// + /// + /// If is 0 and is equal to the size of + /// the currently created buffer, its whole contents are replaced. + /// + /// + /// If is 0 and is greater than the + /// size of the currently created buffer, a new buffer is created + /// containing the data. + /// + /// + /// If is 0 and is less than the size of + /// the currently created buffer, only the corresponding region + /// is updated. + /// + /// + /// If is NOT 0 and + + /// is greater than the size of the currently + /// created buffer, the update fails. + /// + /// + /// No additional checks are performed on the size of the . + /// Passing invalid arguments will lead to undefined behavior. + /// + /// + /// Array of vertices to copy from + /// Number of vertices to copy + /// Offset in the buffer to copy to + //////////////////////////////////////////////////////////// + public bool Update(Vertex[] vertices, uint vertexCount, uint offset) + { + unsafe { - unsafe + fixed (Vertex* verts = vertices) { - fixed (Vertex* verts = vertices) - { - return sfVertexBuffer_update(CPointer, verts, vertexCount, offset); - } + return sfVertexBuffer_update(CPointer, verts, vertexCount, offset); } } + } - //////////////////////////////////////////////////////////// - /// - /// Update a part of the buffer from a [] - /// - /// - /// - /// If the length of is equal - /// to the current size of the buffer, the entire buffer is replaced. - /// - /// - /// If the length of is greater than the - /// current size of the buffer, a new buffer is created containing - /// the data. - /// - /// - /// If the length of is less than the - /// current size of the buffer, only the first .Length - /// vertices are replaced. - /// - /// - /// No additional checks are performed on .Length. - /// Passing invalid arguments will lead to undefined behavior. - /// - /// - /// Array of vertices to copy to the buffer - //////////////////////////////////////////////////////////// - public bool Update(Vertex[] vertices) => Update(vertices, (uint)vertices.Length, 0); - - //////////////////////////////////////////////////////////// - /// - /// Update a part of the buffer from a [] - /// - /// - /// - /// is specified as the number of vertices to skip - /// from the beginning of the buffer. - /// - /// - /// If is 0 and .Length - /// is equal to the size of the currently created buffer, its whole contents are replaced. - /// - /// - /// If is 0 and .Length - /// is greater than the size of the currently created buffer, a new buffer is created - /// containing the data. - /// - /// - /// If is 0 and .Length - /// is less than the size of the currently created buffer, only the first - /// .Length vertices are replaced. - /// - /// - /// If is NOT 0 and + - /// .Length is greater than the size of the currently - /// created buffer, the update fails. - /// - /// - /// No additional checks are performed on the size of the . - /// Passing invalid arguments will lead to undefined behavior. - /// - /// - /// Array of vertices to copy to the buffer - /// Offset in the buffer to copy to - //////////////////////////////////////////////////////////// - public bool Update(Vertex[] vertices, uint offset) => Update(vertices, (uint)vertices.Length, offset); - - //////////////////////////////////////////////////////////// - /// - /// Copy the contents of another into this buffer - /// - /// VertexBuffer whose contents to copy from - //////////////////////////////////////////////////////////// - public bool Update(VertexBuffer other) => sfVertexBuffer_updateFromVertexBuffer(CPointer, other.CPointer); - - //////////////////////////////////////////////////////////// - /// - /// Swap the contents of another into this buffer - /// - /// VertexBuffer whose contents to swap with - //////////////////////////////////////////////////////////// - public void Swap(VertexBuffer other) => sfVertexBuffer_swap(CPointer, other.CPointer); - - //////////////////////////////////////////////////////////// - /// - /// Handle the destruction of the object - /// - /// Is the GC disposing the object, or is it an explicit call ? - //////////////////////////////////////////////////////////// - protected override void Destroy(bool disposing) => sfVertexBuffer_destroy(CPointer); - - //////////////////////////////////////////////////////////// - /// - /// Draw the to a - /// - /// Render target to draw to - /// Current render states - //////////////////////////////////////////////////////////// - public void Draw(IRenderTarget target, RenderStates states) - { - var marshaledStates = states.Marshal(); + //////////////////////////////////////////////////////////// + /// + /// Update a part of the buffer from a [] + /// + /// + /// + /// If the length of is equal + /// to the current size of the buffer, the entire buffer is replaced. + /// + /// + /// If the length of is greater than the + /// current size of the buffer, a new buffer is created containing + /// the data. + /// + /// + /// If the length of is less than the + /// current size of the buffer, only the first .Length + /// vertices are replaced. + /// + /// + /// No additional checks are performed on .Length. + /// Passing invalid arguments will lead to undefined behavior. + /// + /// + /// Array of vertices to copy to the buffer + //////////////////////////////////////////////////////////// + public bool Update(Vertex[] vertices) => Update(vertices, (uint)vertices.Length, 0); - if (target is RenderWindow window) - { - sfRenderWindow_drawVertexBuffer(window.CPointer, CPointer, ref marshaledStates); - } - else if (target is RenderTexture texture) - { - sfRenderTexture_drawVertexBuffer(texture.CPointer, CPointer, ref marshaledStates); - } - } + //////////////////////////////////////////////////////////// + /// + /// Update a part of the buffer from a [] + /// + /// + /// + /// is specified as the number of vertices to skip + /// from the beginning of the buffer. + /// + /// + /// If is 0 and .Length + /// is equal to the size of the currently created buffer, its whole contents are replaced. + /// + /// + /// If is 0 and .Length + /// is greater than the size of the currently created buffer, a new buffer is created + /// containing the data. + /// + /// + /// If is 0 and .Length + /// is less than the size of the currently created buffer, only the first + /// .Length vertices are replaced. + /// + /// + /// If is NOT 0 and + + /// .Length is greater than the size of the currently + /// created buffer, the update fails. + /// + /// + /// No additional checks are performed on the size of the . + /// Passing invalid arguments will lead to undefined behavior. + /// + /// + /// Array of vertices to copy to the buffer + /// Offset in the buffer to copy to + //////////////////////////////////////////////////////////// + public bool Update(Vertex[] vertices, uint offset) => Update(vertices, (uint)vertices.Length, offset); + + //////////////////////////////////////////////////////////// + /// + /// Copy the contents of another into this buffer + /// + /// VertexBuffer whose contents to copy from + //////////////////////////////////////////////////////////// + public bool Update(VertexBuffer other) => sfVertexBuffer_updateFromVertexBuffer(CPointer, other.CPointer); - //////////////////////////////////////////////////////////// - /// - /// Draw the vertex buffer to a render target - /// - /// Render target to draw to - /// Index of the first vertex to render - /// Number of vertices to render - /// Current render states - //////////////////////////////////////////////////////////// - public void Draw(IRenderTarget target, uint firstVertex, uint vertexCount, RenderStates states) + //////////////////////////////////////////////////////////// + /// + /// Swap the contents of another into this buffer + /// + /// VertexBuffer whose contents to swap with + //////////////////////////////////////////////////////////// + public void Swap(VertexBuffer other) => sfVertexBuffer_swap(CPointer, other.CPointer); + + //////////////////////////////////////////////////////////// + /// + /// Handle the destruction of the object + /// + /// Is the GC disposing the object, or is it an explicit call ? + //////////////////////////////////////////////////////////// + protected override void Destroy(bool disposing) => sfVertexBuffer_destroy(CPointer); + + //////////////////////////////////////////////////////////// + /// + /// Draw the to a + /// + /// Render target to draw to + /// Current render states + //////////////////////////////////////////////////////////// + public void Draw(IRenderTarget target, RenderStates states) + { + var marshaledStates = states.Marshal(); + + if (target is RenderWindow window) + { + sfRenderWindow_drawVertexBuffer(window.CPointer, CPointer, ref marshaledStates); + } + else if (target is RenderTexture texture) { - var marshaledStates = states.Marshal(); + sfRenderTexture_drawVertexBuffer(texture.CPointer, CPointer, ref marshaledStates); + } + } - if (target is RenderWindow window) - { - sfRenderWindow_drawVertexBufferRange(window.CPointer, CPointer, (UIntPtr)firstVertex, (UIntPtr)vertexCount, ref marshaledStates); - } - else if (target is RenderTexture texture) - { - sfRenderTexture_drawVertexBufferRange(texture.CPointer, CPointer, (UIntPtr)firstVertex, (UIntPtr)vertexCount, ref marshaledStates); - } + //////////////////////////////////////////////////////////// + /// + /// Draw the vertex buffer to a render target + /// + /// Render target to draw to + /// Index of the first vertex to render + /// Number of vertices to render + /// Current render states + //////////////////////////////////////////////////////////// + public void Draw(IRenderTarget target, uint firstVertex, uint vertexCount, RenderStates states) + { + var marshaledStates = states.Marshal(); + + if (target is RenderWindow window) + { + sfRenderWindow_drawVertexBufferRange(window.CPointer, CPointer, (UIntPtr)firstVertex, (UIntPtr)vertexCount, ref marshaledStates); } + else if (target is RenderTexture texture) + { + sfRenderTexture_drawVertexBufferRange(texture.CPointer, CPointer, (UIntPtr)firstVertex, (UIntPtr)vertexCount, ref marshaledStates); + } + } - #region Imports - [DllImport(CSFML.Graphics, CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] - private static extern IntPtr sfVertexBuffer_create(uint vertexCount, PrimitiveType type, UsageSpecifier usage); + #region Imports + [DllImport(CSFML.Graphics, CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] + private static extern IntPtr sfVertexBuffer_create(uint vertexCount, PrimitiveType type, UsageSpecifier usage); - [DllImport(CSFML.Graphics, CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] - private static extern IntPtr sfVertexBuffer_copy(IntPtr copy); + [DllImport(CSFML.Graphics, CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] + private static extern IntPtr sfVertexBuffer_copy(IntPtr copy); - [DllImport(CSFML.Graphics, CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] - private static extern void sfVertexBuffer_destroy(IntPtr cPointer); + [DllImport(CSFML.Graphics, CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] + private static extern void sfVertexBuffer_destroy(IntPtr cPointer); - [DllImport(CSFML.Graphics, CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] - private static extern uint sfVertexBuffer_getVertexCount(IntPtr cPointer); + [DllImport(CSFML.Graphics, CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] + private static extern uint sfVertexBuffer_getVertexCount(IntPtr cPointer); - [DllImport(CSFML.Graphics, CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] - [return: MarshalAs(UnmanagedType.I1)] - private static extern unsafe bool sfVertexBuffer_update(IntPtr cPointer, Vertex* vertices, uint vertexCount, uint offset); + [DllImport(CSFML.Graphics, CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] + [return: MarshalAs(UnmanagedType.I1)] + private static extern unsafe bool sfVertexBuffer_update(IntPtr cPointer, Vertex* vertices, uint vertexCount, uint offset); - [DllImport(CSFML.Graphics, CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] - [return: MarshalAs(UnmanagedType.I1)] - private static extern bool sfVertexBuffer_updateFromVertexBuffer(IntPtr cPointer, IntPtr other); + [DllImport(CSFML.Graphics, CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] + [return: MarshalAs(UnmanagedType.I1)] + private static extern bool sfVertexBuffer_updateFromVertexBuffer(IntPtr cPointer, IntPtr other); - [DllImport(CSFML.Graphics, CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] - private static extern void sfVertexBuffer_swap(IntPtr cPointer, IntPtr other); + [DllImport(CSFML.Graphics, CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] + private static extern void sfVertexBuffer_swap(IntPtr cPointer, IntPtr other); - [DllImport(CSFML.Graphics, CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] - private static extern uint sfVertexBuffer_getNativeHandle(IntPtr cPointer); + [DllImport(CSFML.Graphics, CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] + private static extern uint sfVertexBuffer_getNativeHandle(IntPtr cPointer); - [DllImport(CSFML.Graphics, CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] - private static extern void sfVertexBuffer_setPrimitiveType(IntPtr cPointer, PrimitiveType primitiveType); + [DllImport(CSFML.Graphics, CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] + private static extern void sfVertexBuffer_setPrimitiveType(IntPtr cPointer, PrimitiveType primitiveType); - [DllImport(CSFML.Graphics, CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] - private static extern PrimitiveType sfVertexBuffer_getPrimitiveType(IntPtr cPointer); + [DllImport(CSFML.Graphics, CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] + private static extern PrimitiveType sfVertexBuffer_getPrimitiveType(IntPtr cPointer); - [DllImport(CSFML.Graphics, CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] - private static extern void sfVertexBuffer_setUsage(IntPtr cPointer, UsageSpecifier usageType); + [DllImport(CSFML.Graphics, CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] + private static extern void sfVertexBuffer_setUsage(IntPtr cPointer, UsageSpecifier usageType); - [DllImport(CSFML.Graphics, CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] - private static extern UsageSpecifier sfVertexBuffer_getUsage(IntPtr cPointer); + [DllImport(CSFML.Graphics, CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] + private static extern UsageSpecifier sfVertexBuffer_getUsage(IntPtr cPointer); - [DllImport(CSFML.Graphics, CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] - private static extern void sfVertexBuffer_bind(IntPtr cPointer); + [DllImport(CSFML.Graphics, CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] + private static extern void sfVertexBuffer_bind(IntPtr cPointer); - [DllImport(CSFML.Graphics, CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] - [return: MarshalAs(UnmanagedType.I1)] - private static extern bool sfVertexBuffer_isAvailable(); + [DllImport(CSFML.Graphics, CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] + [return: MarshalAs(UnmanagedType.I1)] + private static extern bool sfVertexBuffer_isAvailable(); - [DllImport(CSFML.Graphics, CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] - private static extern void sfRenderWindow_drawVertexBuffer(IntPtr cPointer, IntPtr vertexArray, ref RenderStates.MarshalData states); + [DllImport(CSFML.Graphics, CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] + private static extern void sfRenderWindow_drawVertexBuffer(IntPtr cPointer, IntPtr vertexArray, ref RenderStates.MarshalData states); - [DllImport(CSFML.Graphics, CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] - private static extern void sfRenderWindow_drawVertexBufferRange(IntPtr cPointer, IntPtr vertexBuffer, UIntPtr firstVertex, UIntPtr vertexCount, ref RenderStates.MarshalData states); + [DllImport(CSFML.Graphics, CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] + private static extern void sfRenderWindow_drawVertexBufferRange(IntPtr cPointer, IntPtr vertexBuffer, UIntPtr firstVertex, UIntPtr vertexCount, ref RenderStates.MarshalData states); - [DllImport(CSFML.Graphics, CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] - private static extern void sfRenderTexture_drawVertexBuffer(IntPtr cPointer, IntPtr vertexBuffer, ref RenderStates.MarshalData states); + [DllImport(CSFML.Graphics, CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] + private static extern void sfRenderTexture_drawVertexBuffer(IntPtr cPointer, IntPtr vertexBuffer, ref RenderStates.MarshalData states); - [DllImport(CSFML.Graphics, CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] - private static extern void sfRenderTexture_drawVertexBufferRange(IntPtr cPointer, IntPtr vertexBuffer, UIntPtr firstVertex, UIntPtr vertexCount, ref RenderStates.MarshalData states); - #endregion - } + [DllImport(CSFML.Graphics, CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] + private static extern void sfRenderTexture_drawVertexBufferRange(IntPtr cPointer, IntPtr vertexBuffer, UIntPtr firstVertex, UIntPtr vertexCount, ref RenderStates.MarshalData states); + #endregion } diff --git a/src/SFML.Graphics/View.cs b/src/SFML.Graphics/View.cs index 600512ee..517235f3 100644 --- a/src/SFML.Graphics/View.cs +++ b/src/SFML.Graphics/View.cs @@ -3,253 +3,252 @@ using System.Security; using SFML.System; -namespace SFML.Graphics +namespace SFML.Graphics; + +//////////////////////////////////////////////////////////// +/// +/// This class defines a view (position, size, etc.) ; +/// you can consider it as a 2D camera +/// +/// +/// See also the note on coordinates and undistorted rendering in SFML.Graphics.Transformable. +/// +//////////////////////////////////////////////////////////// +public class View : ObjectBase { //////////////////////////////////////////////////////////// /// - /// This class defines a view (position, size, etc.) ; - /// you can consider it as a 2D camera + /// Create a default view (1000x1000) /// - /// - /// See also the note on coordinates and undistorted rendering in SFML.Graphics.Transformable. - /// //////////////////////////////////////////////////////////// - public class View : ObjectBase + public View() : + base(sfView_create()) { - //////////////////////////////////////////////////////////// - /// - /// Create a default view (1000x1000) - /// - //////////////////////////////////////////////////////////// - public View() : - base(sfView_create()) - { - } + } - //////////////////////////////////////////////////////////// - /// - /// Construct the view from a rectangle - /// - /// Rectangle defining the position and size of the view - //////////////////////////////////////////////////////////// - public View(FloatRect viewRect) : - base(sfView_createFromRect(viewRect)) - { - } + //////////////////////////////////////////////////////////// + /// + /// Construct the view from a rectangle + /// + /// Rectangle defining the position and size of the view + //////////////////////////////////////////////////////////// + public View(FloatRect viewRect) : + base(sfView_createFromRect(viewRect)) + { + } - //////////////////////////////////////////////////////////// - /// - /// Construct the view from its center and size - /// - /// Center of the view - /// Size of the view - //////////////////////////////////////////////////////////// - public View(Vector2f center, Vector2f size) : - base(sfView_create()) - { - Center = center; - Size = size; - } + //////////////////////////////////////////////////////////// + /// + /// Construct the view from its center and size + /// + /// Center of the view + /// Size of the view + //////////////////////////////////////////////////////////// + public View(Vector2f center, Vector2f size) : + base(sfView_create()) + { + Center = center; + Size = size; + } - //////////////////////////////////////////////////////////// - /// - /// Construct the view from another view - /// - /// View to copy - //////////////////////////////////////////////////////////// - public View(View copy) : - base(sfView_copy(copy.CPointer)) - { - } + //////////////////////////////////////////////////////////// + /// + /// Construct the view from another view + /// + /// View to copy + //////////////////////////////////////////////////////////// + public View(View copy) : + base(sfView_copy(copy.CPointer)) + { + } - //////////////////////////////////////////////////////////// - /// - /// Center of the view - /// - //////////////////////////////////////////////////////////// - public Vector2f Center - { - get => sfView_getCenter(CPointer); - set => sfView_setCenter(CPointer, value); - } + //////////////////////////////////////////////////////////// + /// + /// Center of the view + /// + //////////////////////////////////////////////////////////// + public Vector2f Center + { + get => sfView_getCenter(CPointer); + set => sfView_setCenter(CPointer, value); + } - //////////////////////////////////////////////////////////// - /// - /// Half-size of the view - /// - //////////////////////////////////////////////////////////// - public Vector2f Size - { - get => sfView_getSize(CPointer); - set => sfView_setSize(CPointer, value); - } + //////////////////////////////////////////////////////////// + /// + /// Half-size of the view + /// + //////////////////////////////////////////////////////////// + public Vector2f Size + { + get => sfView_getSize(CPointer); + set => sfView_setSize(CPointer, value); + } - //////////////////////////////////////////////////////////// - /// - /// Rotation of the view, in degrees - /// - //////////////////////////////////////////////////////////// - public Angle Rotation - { - get => Angle.FromDegrees(sfView_getRotation(CPointer)); - set => sfView_setRotation(CPointer, value.Degrees); - } + //////////////////////////////////////////////////////////// + /// + /// Rotation of the view, in degrees + /// + //////////////////////////////////////////////////////////// + public Angle Rotation + { + get => Angle.FromDegrees(sfView_getRotation(CPointer)); + set => sfView_setRotation(CPointer, value.Degrees); + } - //////////////////////////////////////////////////////////// - /// - /// Target viewport of the view, defined as a factor of the - /// size of the target to which the view is applied - /// - //////////////////////////////////////////////////////////// - public FloatRect Viewport - { - get => sfView_getViewport(CPointer); - set => sfView_setViewport(CPointer, value); - } + //////////////////////////////////////////////////////////// + /// + /// Target viewport of the view, defined as a factor of the + /// size of the target to which the view is applied + /// + //////////////////////////////////////////////////////////// + public FloatRect Viewport + { + get => sfView_getViewport(CPointer); + set => sfView_setViewport(CPointer, value); + } - //////////////////////////////////////////////////////////// - /// - /// 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. - /// - //////////////////////////////////////////////////////////// - public FloatRect Scissor - { - get => sfView_getScissor(CPointer); - set => sfView_setScissor(CPointer, value); - } + //////////////////////////////////////////////////////////// + /// + /// 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. + /// + //////////////////////////////////////////////////////////// + public FloatRect Scissor + { + get => sfView_getScissor(CPointer); + set => sfView_setScissor(CPointer, value); + } + + //////////////////////////////////////////////////////////// + /// + /// Move the view + /// + /// Offset to move the view + //////////////////////////////////////////////////////////// + public void Move(Vector2f offset) => sfView_move(CPointer, offset); + + //////////////////////////////////////////////////////////// + /// + /// Rotate the view + /// + /// Angle of rotation, in degrees + //////////////////////////////////////////////////////////// + public void Rotate(float angle) => sfView_rotate(CPointer, angle); - //////////////////////////////////////////////////////////// - /// - /// Move the view - /// - /// Offset to move the view - //////////////////////////////////////////////////////////// - public void Move(Vector2f offset) => sfView_move(CPointer, offset); - - //////////////////////////////////////////////////////////// - /// - /// Rotate the view - /// - /// Angle of rotation, in degrees - //////////////////////////////////////////////////////////// - public void Rotate(float angle) => sfView_rotate(CPointer, angle); - - //////////////////////////////////////////////////////////// - /// - /// Resize the view rectangle to simulate a zoom / unzoom effect - /// - /// Zoom factor to apply, relative to the current zoom - //////////////////////////////////////////////////////////// - public void Zoom(float factor) => sfView_zoom(CPointer, factor); - - //////////////////////////////////////////////////////////// - /// - /// Provide a string describing the object - /// - /// String description of the object - //////////////////////////////////////////////////////////// - public override string ToString() + //////////////////////////////////////////////////////////// + /// + /// Resize the view rectangle to simulate a zoom / unzoom effect + /// + /// Zoom factor to apply, relative to the current zoom + //////////////////////////////////////////////////////////// + public void Zoom(float factor) => sfView_zoom(CPointer, factor); + + //////////////////////////////////////////////////////////// + /// + /// Provide a string describing the object + /// + /// String description of the object + //////////////////////////////////////////////////////////// + public override string ToString() + { + if (IsInvalid) { - if (IsInvalid) - { - return MakeDisposedObjectString(); - } - - return "[View]" + - " Center(" + Center + ")" + - " Size(" + Size + ")" + - " Rotation(" + Rotation + ")" + - " Viewport(" + Viewport + ")"; + return MakeDisposedObjectString(); } - //////////////////////////////////////////////////////////// - /// - /// Internal constructor for other classes which need to manipulate raw views - /// - /// Direct pointer to the view object in the C library - //////////////////////////////////////////////////////////// - internal View(IntPtr cPointer) : - base(cPointer) => _external = true; - - //////////////////////////////////////////////////////////// - /// - /// Handle the destruction of the object - /// - /// Is the GC disposing the object, or is it an explicit call ? - //////////////////////////////////////////////////////////// - protected override void Destroy(bool disposing) + return "[View]" + + " Center(" + Center + ")" + + " Size(" + Size + ")" + + " Rotation(" + Rotation + ")" + + " Viewport(" + Viewport + ")"; + } + + //////////////////////////////////////////////////////////// + /// + /// Internal constructor for other classes which need to manipulate raw views + /// + /// Direct pointer to the view object in the C library + //////////////////////////////////////////////////////////// + internal View(IntPtr cPointer) : + base(cPointer) => _external = true; + + //////////////////////////////////////////////////////////// + /// + /// Handle the destruction of the object + /// + /// Is the GC disposing the object, or is it an explicit call ? + //////////////////////////////////////////////////////////// + protected override void Destroy(bool disposing) + { + if (!_external) { - if (!_external) - { - sfView_destroy(CPointer); - } + sfView_destroy(CPointer); } + } - private readonly bool _external; + private readonly bool _external; - #region Imports - [DllImport(CSFML.Graphics, CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] - private static extern IntPtr sfView_create(); + #region Imports + [DllImport(CSFML.Graphics, CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] + private static extern IntPtr sfView_create(); - [DllImport(CSFML.Graphics, CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] - private static extern IntPtr sfView_createFromRect(FloatRect rect); + [DllImport(CSFML.Graphics, CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] + private static extern IntPtr sfView_createFromRect(FloatRect rect); - [DllImport(CSFML.Graphics, CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] - private static extern IntPtr sfView_copy(IntPtr view); + [DllImport(CSFML.Graphics, CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] + private static extern IntPtr sfView_copy(IntPtr view); - [DllImport(CSFML.Graphics, CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] - private static extern void sfView_destroy(IntPtr view); + [DllImport(CSFML.Graphics, CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] + private static extern void sfView_destroy(IntPtr view); - [DllImport(CSFML.Graphics, CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] - private static extern void sfView_setCenter(IntPtr view, Vector2f center); + [DllImport(CSFML.Graphics, CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] + private static extern void sfView_setCenter(IntPtr view, Vector2f center); - [DllImport(CSFML.Graphics, CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] - private static extern void sfView_setSize(IntPtr view, Vector2f size); + [DllImport(CSFML.Graphics, CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] + private static extern void sfView_setSize(IntPtr view, Vector2f size); - [DllImport(CSFML.Graphics, CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] - private static extern void sfView_setRotation(IntPtr view, float angle); + [DllImport(CSFML.Graphics, CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] + private static extern void sfView_setRotation(IntPtr view, float angle); - [DllImport(CSFML.Graphics, CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] - private static extern void sfView_setViewport(IntPtr view, FloatRect viewport); + [DllImport(CSFML.Graphics, CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] + private static extern void sfView_setViewport(IntPtr view, FloatRect viewport); - [DllImport(CSFML.Graphics, CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] - private static extern void sfView_setScissor(IntPtr view, FloatRect viewport); + [DllImport(CSFML.Graphics, CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] + private static extern void sfView_setScissor(IntPtr view, FloatRect viewport); - [DllImport(CSFML.Graphics, CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] - private static extern Vector2f sfView_getCenter(IntPtr view); + [DllImport(CSFML.Graphics, CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] + private static extern Vector2f sfView_getCenter(IntPtr view); - [DllImport(CSFML.Graphics, CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] - private static extern Vector2f sfView_getSize(IntPtr view); + [DllImport(CSFML.Graphics, CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] + private static extern Vector2f sfView_getSize(IntPtr view); - [DllImport(CSFML.Graphics, CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] - private static extern float sfView_getRotation(IntPtr view); + [DllImport(CSFML.Graphics, CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] + private static extern float sfView_getRotation(IntPtr view); - [DllImport(CSFML.Graphics, CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] - private static extern FloatRect sfView_getViewport(IntPtr view); + [DllImport(CSFML.Graphics, CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] + private static extern FloatRect sfView_getViewport(IntPtr view); - [DllImport(CSFML.Graphics, CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] - private static extern FloatRect sfView_getScissor(IntPtr view); + [DllImport(CSFML.Graphics, CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] + private static extern FloatRect sfView_getScissor(IntPtr view); - [DllImport(CSFML.Graphics, CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] - private static extern void sfView_move(IntPtr view, Vector2f offset); + [DllImport(CSFML.Graphics, CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] + private static extern void sfView_move(IntPtr view, Vector2f offset); - [DllImport(CSFML.Graphics, CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] - private static extern void sfView_rotate(IntPtr view, float angle); + [DllImport(CSFML.Graphics, CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] + private static extern void sfView_rotate(IntPtr view, float angle); - [DllImport(CSFML.Graphics, CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] - private static extern void sfView_zoom(IntPtr view, float factor); - #endregion - } + [DllImport(CSFML.Graphics, CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] + private static extern void sfView_zoom(IntPtr view, float factor); + #endregion } diff --git a/src/SFML.System/Allocation.cs b/src/SFML.System/Allocation.cs index 2c96f8a4..d85e8f45 100644 --- a/src/SFML.System/Allocation.cs +++ b/src/SFML.System/Allocation.cs @@ -2,25 +2,24 @@ using System.Security; using System; -namespace SFML.System +namespace SFML.System; + +/// +/// Contains functions related to memory allocation. +/// For internal use only. +/// +public static class Allocation { /// - /// Contains functions related to memory allocation. - /// For internal use only. + /// This function deallocates the memory being pointed to + /// using the free function from the C standard library. + /// + /// The memory must have been previously allocated using a call + /// to malloc. /// - public static class Allocation - { - /// - /// This function deallocates the memory being pointed to - /// using the free function from the C standard library. - /// - /// The memory must have been previously allocated using a call - /// to malloc. - /// - /// Pointer to the memory to deallocate - public static void Free(IntPtr ptr) => sfFree(ptr); + /// Pointer to the memory to deallocate + public static void Free(IntPtr ptr) => sfFree(ptr); - [DllImport(CSFML.System, CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] - private static extern void sfFree(IntPtr ptr); - } + [DllImport(CSFML.System, CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] + private static extern void sfFree(IntPtr ptr); } diff --git a/src/SFML.System/Angle.cs b/src/SFML.System/Angle.cs index 67e11ebb..821b29db 100644 --- a/src/SFML.System/Angle.cs +++ b/src/SFML.System/Angle.cs @@ -1,335 +1,334 @@ using System; using System.Diagnostics; -namespace SFML.System +namespace SFML.System; + +//////////////////////////////////////////////////////////// +/// +/// Represents an angle value +/// +//////////////////////////////////////////////////////////// +public readonly struct Angle : IEquatable { + private const float Tau = (float)(2 * Math.PI); + private const float Pi = (float)Math.PI; + private const double DegreesInRadian = 180.0 / Math.PI; + private const double RadiansInDegree = Math.PI / 180.0; + + //////////////////////////////////////////////////////////// + /// + /// Construct an angle value from a number of radians + /// + /// Number of radians + /// Angle value constructed from the number of radians + //////////////////////////////////////////////////////////// + public static Angle FromRadians(float radians) => new(radians); + + //////////////////////////////////////////////////////////// + /// + /// Construct an angle value from a number of degrees + /// + /// Number of degrees + /// Angle value constructed from the number of degrees + //////////////////////////////////////////////////////////// + public static Angle FromDegrees(float degrees) => new((float)(degrees * RadiansInDegree)); + + //////////////////////////////////////////////////////////// + /// + /// Predefined 0 degree angle value + /// + //////////////////////////////////////////////////////////// + public static readonly Angle Zero; + + //////////////////////////////////////////////////////////// + /// + /// Gets the angle's value in radians + /// + //////////////////////////////////////////////////////////// + public float Radians { get; } + + //////////////////////////////////////////////////////////// + /// + /// Gets the angle's value in degrees + /// + //////////////////////////////////////////////////////////// + public float Degrees => (float)(Radians * DegreesInRadian); + + //////////////////////////////////////////////////////////// + /// + /// 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: + /// + /// + /// + /// + /// + /// + /// + /// + /// + /// + /// + /// + /// + /// + /// + /// + ///
signedunsigned
char[-128, 128)[0, 256)
Angle[-180°, 180°)[0°, 360°)
+ ///
+ /// Signed angle, wrapped to [-180°, 180°) + //////////////////////////////////////////////////////////// + public Angle WrapSigned() => FromRadians(PositiveRemainder(Radians + Pi, Tau) - Pi); + + //////////////////////////////////////////////////////////// + /// + /// 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: + /// + /// + /// + /// + /// + /// + /// + /// + /// + /// + /// + /// + /// + /// + /// + /// + ///
signedunsigned
char[-128, 128)[0, 256)
Angle[-180°, 180°)[0°, 360°)
+ ///
+ /// Unsigned angle, wrapped to [0°, 360°) + //////////////////////////////////////////////////////////// + public Angle WrapUnsigned() => FromRadians(PositiveRemainder(Radians, Tau)); + + //////////////////////////////////////////////////////////// + /// + /// Overload of == operator to compare two angle values + /// + /// Does not automatically wrap the angle value + /// Left operand (an angle) + /// Right operand (an angle) + /// True if both angle values are equal + //////////////////////////////////////////////////////////// + public static bool operator ==(Angle left, Angle right) => left.Radians == right.Radians; + + //////////////////////////////////////////////////////////// + /// + /// Overload of != operator to compare two angle values + /// + /// Does not automatically wrap the angle value + /// Left operand (an angle) + /// Right operand (an angle) + /// True if both angle values are different + //////////////////////////////////////////////////////////// + public static bool operator !=(Angle left, Angle right) => left.Radians != right.Radians; + + //////////////////////////////////////////////////////////// + /// + /// Overload of < operator to compare two angle values + /// + /// Does not automatically wrap the angle value + /// Left operand (an angle) + /// Right operand (an angle) + /// True if is less than + //////////////////////////////////////////////////////////// + public static bool operator <(Angle left, Angle right) => left.Radians < right.Radians; + + //////////////////////////////////////////////////////////// + /// + /// Overload of <= operator to compare two angle values + /// + /// Does not automatically wrap the angle value + /// Left operand (an angle) + /// Right operand (an angle) + /// True if is less than or equal to + //////////////////////////////////////////////////////////// + public static bool operator <=(Angle left, Angle right) => left.Radians <= right.Radians; + + //////////////////////////////////////////////////////////// + /// + /// Overload of > operator to compare two angle values + /// + /// Does not automatically wrap the angle value + /// Left operand (an angle) + /// Right operand (an angle) + /// True if is greater than + //////////////////////////////////////////////////////////// + public static bool operator >(Angle left, Angle right) => left.Radians > right.Radians; + + //////////////////////////////////////////////////////////// + /// + /// Overload of >= operator to compare two angle values + /// + /// Does not automatically wrap the angle value + /// Left operand (an angle) + /// Right operand (an angle) + /// True if is greater than or equal to + //////////////////////////////////////////////////////////// + public static bool operator >=(Angle left, Angle right) => left.Radians >= right.Radians; + //////////////////////////////////////////////////////////// /// - /// Represents an angle value + /// Overload of binary + operator to add two angle values /// + /// Left operand (an angle) + /// Right operand (an angle) + /// Sum of the two angle values //////////////////////////////////////////////////////////// - public readonly struct Angle + public static Angle operator +(Angle left, Angle right) => FromRadians(left.Radians + right.Radians); + + //////////////////////////////////////////////////////////// + /// + /// Overload of unary - operator to negate an angle value + /// + /// Represents a rotation in the opposite direction. + /// + /// Right operand (an angle) + /// Negative of the angle value + //////////////////////////////////////////////////////////// + public static Angle operator -(Angle right) => FromRadians(-right.Radians); + + //////////////////////////////////////////////////////////// + /// + /// Overload of binary - operator to substract two angle values + /// + /// Left operand (an angle) + /// Right operand (an angle) + /// Difference of the two angle values + //////////////////////////////////////////////////////////// + public static Angle operator -(Angle left, Angle right) => FromRadians(left.Radians - right.Radians); + + //////////////////////////////////////////////////////////// + /// + /// Overload of binary * operator to scale an angle value + /// + /// Left operand (an angle) + /// Right operand (a number) + /// multiplied by + //////////////////////////////////////////////////////////// + public static Angle operator *(Angle left, float right) => FromRadians(left.Radians * right); + + //////////////////////////////////////////////////////////// + /// + /// Overload of binary * operator to scale an angle value + /// + /// Left operand (a number) + /// Right operand (an angle) + /// multiplied by + //////////////////////////////////////////////////////////// + public static Angle operator *(float left, Angle right) => FromRadians(left * right.Radians); + + //////////////////////////////////////////////////////////// + /// + /// Overload of binary / operator to compute the ratio of two angle values + /// + /// Left operand (an angle) + /// Right operand (an angle) + /// divided by + //////////////////////////////////////////////////////////// + public static float operator /(Angle left, Angle right) + { + Debug.Assert(right.Radians != 0f, "Angle.operator/ cannot divide by 0"); + + return left.Radians / right.Radians; + } + + //////////////////////////////////////////////////////////// + /// + /// Overload of binary / operator to scale an angle value + /// + /// Left operand (an angle) + /// Right operand (a number) + /// divided by + //////////////////////////////////////////////////////////// + public static Angle operator /(Angle left, float right) { - private const float Tau = (float)(2 * Math.PI); - private const float Pi = (float)Math.PI; - private const double DegreesInRadian = 180.0 / Math.PI; - private const double RadiansInDegree = Math.PI / 180.0; - - //////////////////////////////////////////////////////////// - /// - /// Construct an angle value from a number of radians - /// - /// Number of radians - /// Angle value constructed from the number of radians - //////////////////////////////////////////////////////////// - public static Angle FromRadians(float radians) => new Angle(radians); - - //////////////////////////////////////////////////////////// - /// - /// Construct an angle value from a number of degrees - /// - /// Number of degrees - /// Angle value constructed from the number of degrees - //////////////////////////////////////////////////////////// - public static Angle FromDegrees(float degrees) => new Angle((float)(degrees * RadiansInDegree)); - - //////////////////////////////////////////////////////////// - /// - /// Predefined 0 degree angle value - /// - //////////////////////////////////////////////////////////// - public static readonly Angle Zero; - - //////////////////////////////////////////////////////////// - /// - /// Gets the angle's value in radians - /// - //////////////////////////////////////////////////////////// - public float Radians { get; } - - //////////////////////////////////////////////////////////// - /// - /// Gets the angle's value in degrees - /// - //////////////////////////////////////////////////////////// - public float Degrees => (float)(Radians * DegreesInRadian); - - //////////////////////////////////////////////////////////// - /// - /// 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: - /// - /// - /// - /// - /// - /// - /// - /// - /// - /// - /// - /// - /// - /// - /// - /// - ///
signedunsigned
char[-128, 128)[0, 256)
Angle[-180°, 180°)[0°, 360°)
- ///
- /// Signed angle, wrapped to [-180°, 180°) - //////////////////////////////////////////////////////////// - public Angle WrapSigned() => FromRadians(PositiveRemainder(Radians + Pi, Tau) - Pi); - - //////////////////////////////////////////////////////////// - /// - /// 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: - /// - /// - /// - /// - /// - /// - /// - /// - /// - /// - /// - /// - /// - /// - /// - /// - ///
signedunsigned
char[-128, 128)[0, 256)
Angle[-180°, 180°)[0°, 360°)
- ///
- /// Unsigned angle, wrapped to [0°, 360°) - //////////////////////////////////////////////////////////// - public Angle WrapUnsigned() => FromRadians((float)PositiveRemainder(Radians, Tau)); - - //////////////////////////////////////////////////////////// - /// - /// Overload of == operator to compare two angle values - /// - /// Does not automatically wrap the angle value - /// Left operand (an angle) - /// Right operand (an angle) - /// True if both angle values are equal - //////////////////////////////////////////////////////////// - public static bool operator ==(Angle left, Angle right) => left.Radians == right.Radians; - - //////////////////////////////////////////////////////////// - /// - /// Overload of != operator to compare two angle values - /// - /// Does not automatically wrap the angle value - /// Left operand (an angle) - /// Right operand (an angle) - /// True if both angle values are different - //////////////////////////////////////////////////////////// - public static bool operator !=(Angle left, Angle right) => left.Radians != right.Radians; - - //////////////////////////////////////////////////////////// - /// - /// Overload of < operator to compare two angle values - /// - /// Does not automatically wrap the angle value - /// Left operand (an angle) - /// Right operand (an angle) - /// True if is less than - //////////////////////////////////////////////////////////// - public static bool operator <(Angle left, Angle right) => left.Radians < right.Radians; - - //////////////////////////////////////////////////////////// - /// - /// Overload of <= operator to compare two angle values - /// - /// Does not automatically wrap the angle value - /// Left operand (an angle) - /// Right operand (an angle) - /// True if is less than or equal to - //////////////////////////////////////////////////////////// - public static bool operator <=(Angle left, Angle right) => left.Radians <= right.Radians; - - //////////////////////////////////////////////////////////// - /// - /// Overload of > operator to compare two angle values - /// - /// Does not automatically wrap the angle value - /// Left operand (an angle) - /// Right operand (an angle) - /// True if is greater than - //////////////////////////////////////////////////////////// - public static bool operator >(Angle left, Angle right) => left.Radians > right.Radians; - - //////////////////////////////////////////////////////////// - /// - /// Overload of >= operator to compare two angle values - /// - /// Does not automatically wrap the angle value - /// Left operand (an angle) - /// Right operand (an angle) - /// True if is greater than or equal to - //////////////////////////////////////////////////////////// - public static bool operator >=(Angle left, Angle right) => left.Radians >= right.Radians; - - //////////////////////////////////////////////////////////// - /// - /// Overload of binary + operator to add two angle values - /// - /// Left operand (an angle) - /// Right operand (an angle) - /// Sum of the two angle values - //////////////////////////////////////////////////////////// - public static Angle operator +(Angle left, Angle right) => FromRadians(left.Radians + right.Radians); - - //////////////////////////////////////////////////////////// - /// - /// Overload of unary - operator to negate an angle value - /// - /// Represents a rotation in the opposite direction. - /// - /// Right operand (an angle) - /// Negative of the angle value - //////////////////////////////////////////////////////////// - public static Angle operator -(Angle right) => FromRadians(-right.Radians); - - //////////////////////////////////////////////////////////// - /// - /// Overload of binary - operator to substract two angle values - /// - /// Left operand (an angle) - /// Right operand (an angle) - /// Difference of the two angle values - //////////////////////////////////////////////////////////// - public static Angle operator -(Angle left, Angle right) => FromRadians(left.Radians - right.Radians); - - //////////////////////////////////////////////////////////// - /// - /// Overload of binary * operator to scale an angle value - /// - /// Left operand (an angle) - /// Right operand (a number) - /// multiplied by - //////////////////////////////////////////////////////////// - public static Angle operator *(Angle left, float right) => FromRadians(left.Radians * right); - - //////////////////////////////////////////////////////////// - /// - /// Overload of binary * operator to scale an angle value - /// - /// Left operand (a number) - /// Right operand (an angle) - /// multiplied by - //////////////////////////////////////////////////////////// - public static Angle operator *(float left, Angle right) => FromRadians(left * right.Radians); - - //////////////////////////////////////////////////////////// - /// - /// Overload of binary / operator to compute the ratio of two angle values - /// - /// Left operand (an angle) - /// Right operand (an angle) - /// divided by - //////////////////////////////////////////////////////////// - public static float operator /(Angle left, Angle right) - { - Debug.Assert(right.Radians != 0f, "Angle.operator/ cannot divide by 0"); - - return left.Radians / right.Radians; - } - - //////////////////////////////////////////////////////////// - /// - /// Overload of binary / operator to scale an angle value - /// - /// Left operand (an angle) - /// Right operand (a number) - /// divided by - //////////////////////////////////////////////////////////// - public static Angle operator /(Angle left, float right) - { - Debug.Assert(right != 0f, "Angle.operator/ cannot divide by 0"); - - return FromRadians(left.Radians / right); - } - - //////////////////////////////////////////////////////////// - /// - /// Overload of binary % operator to compute modulo of an angle value - /// - /// Right hand angle must be greater than zero. - /// - /// Examples: - /// - /// sf::degrees(90) % sf::degrees(40) // 10 degrees - /// sf::degrees(-90) % sf::degrees(40) // 30 degrees (not -10) - /// - /// - /// Left operand (an angle) - /// Right operand (an angle) - /// modulo - //////////////////////////////////////////////////////////// - public static Angle operator %(Angle left, Angle right) - { - Debug.Assert(right.Radians != 0f, "Angle.operator% cannot modulus by 0"); - - return FromRadians((float)PositiveRemainder(left.Radians, right.Radians)); - } - - //////////////////////////////////////////////////////////// - /// - /// Compare angle and object and checks if they are equal - /// - /// Object to check - /// Object and angle are equal - //////////////////////////////////////////////////////////// - public override bool Equals(object obj) => (obj is Angle angle) && Equals(angle); - - /////////////////////////////////////////////////////////// - /// - /// Compare two angles and checks if they are equal - /// - /// Angle to check - /// Angles are equal - //////////////////////////////////////////////////////////// - public bool Equals(Angle other) => Radians == other.Radians; - - //////////////////////////////////////////////////////////// - /// - /// Provide a integer describing the object - /// - /// Integer description of the object - //////////////////////////////////////////////////////////// - public override int GetHashCode() => Radians.GetHashCode(); - - //////////////////////////////////////////////////////////// - /// - /// Provide a string describing the object - /// - /// String description of the object - //////////////////////////////////////////////////////////// - public override string ToString() => "[Angle]" + - " Radians(" + Radians + ")" + - " Degrees(" + Degrees + ")"; - - private Angle(float radians) => Radians = radians; - - private static float PositiveRemainder(float a, float b) - { - Debug.Assert(b > 0, "Cannot calculate remainder with non-positive divisor"); - - var val = a - ((int)(a / b) * b); - return val >= 0.0 ? val : val + b; - } + Debug.Assert(right != 0f, "Angle.operator/ cannot divide by 0"); + + return FromRadians(left.Radians / right); + } + + //////////////////////////////////////////////////////////// + /// + /// Overload of binary % operator to compute modulo of an angle value + /// + /// Right hand angle must be greater than zero. + /// + /// Examples: + /// + /// sf::degrees(90) % sf::degrees(40) // 10 degrees + /// sf::degrees(-90) % sf::degrees(40) // 30 degrees (not -10) + /// + /// + /// Left operand (an angle) + /// Right operand (an angle) + /// modulo + //////////////////////////////////////////////////////////// + public static Angle operator %(Angle left, Angle right) + { + Debug.Assert(right.Radians != 0f, "Angle.operator% cannot modulus by 0"); + + return FromRadians(PositiveRemainder(left.Radians, right.Radians)); + } + + //////////////////////////////////////////////////////////// + /// + /// Compare angle and object and checks if they are equal + /// + /// Object to check + /// Object and angle are equal + //////////////////////////////////////////////////////////// + public override bool Equals(object obj) => (obj is Angle angle) && Equals(angle); + + /////////////////////////////////////////////////////////// + /// + /// Compare two angles and checks if they are equal + /// + /// Angle to check + /// Angles are equal + //////////////////////////////////////////////////////////// + public bool Equals(Angle other) => Radians == other.Radians; + + //////////////////////////////////////////////////////////// + /// + /// Provide a integer describing the object + /// + /// Integer description of the object + //////////////////////////////////////////////////////////// + public override int GetHashCode() => Radians.GetHashCode(); + + //////////////////////////////////////////////////////////// + /// + /// Provide a string describing the object + /// + /// String description of the object + //////////////////////////////////////////////////////////// + public override string ToString() => "[Angle]" + + " Radians(" + Radians + ")" + + " Degrees(" + Degrees + ")"; + + private Angle(float radians) => Radians = radians; + + private static float PositiveRemainder(float a, float b) + { + Debug.Assert(b > 0, "Cannot calculate remainder with non-positive divisor"); + + var val = a - ((int)(a / b) * b); + return val >= 0.0 ? val : val + b; } } diff --git a/src/SFML.System/Buffer.cs b/src/SFML.System/Buffer.cs index 2d5eeb4b..0f33de67 100644 --- a/src/SFML.System/Buffer.cs +++ b/src/SFML.System/Buffer.cs @@ -2,83 +2,82 @@ using System.Runtime.InteropServices; using System.Security; -namespace SFML.System +namespace SFML.System; + +//////////////////////////////////////////////////////////// +/// +/// Internal helper class for CSFML's sfBuffer +/// +//////////////////////////////////////////////////////////// +public class Buffer : ObjectBase { //////////////////////////////////////////////////////////// /// - /// Internal helper class for CSFML's sfBuffer + /// Construct the buffer /// + /// //////////////////////////////////////////////////////////// - public class Buffer : ObjectBase + public Buffer() : + base(sfBuffer_create()) { - //////////////////////////////////////////////////////////// - /// - /// Construct the buffer - /// - /// - //////////////////////////////////////////////////////////// - public Buffer() : - base(sfBuffer_create()) + if (IsInvalid) { - if (IsInvalid) - { - throw new LoadingFailedException("buffer"); - } + throw new LoadingFailedException("buffer"); } + } - //////////////////////////////////////////////////////////// - /// - /// Get a copy of the buffer data - /// - /// A byte array containing the buffer data - //////////////////////////////////////////////////////////// - public byte[] GetData() - { - var size = sfBuffer_getSize(CPointer); - var ptr = sfBuffer_getData(CPointer); + //////////////////////////////////////////////////////////// + /// + /// Get a copy of the buffer data + /// + /// A byte array containing the buffer data + //////////////////////////////////////////////////////////// + public byte[] GetData() + { + var size = sfBuffer_getSize(CPointer); + var ptr = sfBuffer_getData(CPointer); - if (ptr == IntPtr.Zero) - { - return Array.Empty(); - } + if (ptr == IntPtr.Zero) + { + return []; + } - var data = new byte[(int)size]; - Marshal.Copy(ptr, data, 0, (int)size); + var data = new byte[(int)size]; + Marshal.Copy(ptr, data, 0, (int)size); - return data; - } + return data; + } - //////////////////////////////////////////////////////////// - /// - /// Internal constructor - /// - /// Pointer to the object in C library - //////////////////////////////////////////////////////////// - internal Buffer(IntPtr cPointer) : - base(cPointer) - { - } + //////////////////////////////////////////////////////////// + /// + /// Internal constructor + /// + /// Pointer to the object in C library + //////////////////////////////////////////////////////////// + internal Buffer(IntPtr cPointer) : + base(cPointer) + { + } - //////////////////////////////////////////////////////////// - /// - /// Handle the destruction of the object - /// - /// Is the GC disposing the object, or is it an explicit call? - //////////////////////////////////////////////////////////// - protected override void Destroy(bool disposing) => sfBuffer_destroy(CPointer); + //////////////////////////////////////////////////////////// + /// + /// Handle the destruction of the object + /// + /// Is the GC disposing the object, or is it an explicit call? + //////////////////////////////////////////////////////////// + protected override void Destroy(bool disposing) => sfBuffer_destroy(CPointer); - #region Imports - [DllImport(CSFML.System, CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] - private static extern IntPtr sfBuffer_create(); + #region Imports + [DllImport(CSFML.System, CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] + private static extern IntPtr sfBuffer_create(); - [DllImport(CSFML.System, CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] - private static extern void sfBuffer_destroy(IntPtr buffer); + [DllImport(CSFML.System, CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] + private static extern void sfBuffer_destroy(IntPtr buffer); - [DllImport(CSFML.System, CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] - private static extern UIntPtr sfBuffer_getSize(IntPtr buffer); + [DllImport(CSFML.System, CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] + private static extern UIntPtr sfBuffer_getSize(IntPtr buffer); - [DllImport(CSFML.System, CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] - private static extern IntPtr sfBuffer_getData(IntPtr buffer); - #endregion - } + [DllImport(CSFML.System, CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] + private static extern IntPtr sfBuffer_getData(IntPtr buffer); + #endregion } diff --git a/src/SFML.System/Clock.cs b/src/SFML.System/Clock.cs index c9a17ba9..ef2ad9d7 100644 --- a/src/SFML.System/Clock.cs +++ b/src/SFML.System/Clock.cs @@ -2,105 +2,104 @@ using System.Runtime.InteropServices; using System.Security; -namespace SFML.System +namespace SFML.System; + +//////////////////////////////////////////////////////////// +/// +/// Utility class that measures the elapsed time +/// +//////////////////////////////////////////////////////////// +public class Clock : ObjectBase { //////////////////////////////////////////////////////////// /// - /// Utility class that measures the elapsed time + /// Default Constructor + /// + /// The clock starts automatically after being constructed. /// //////////////////////////////////////////////////////////// - public class Clock : ObjectBase - { - //////////////////////////////////////////////////////////// - /// - /// Default Constructor - /// - /// The clock starts automatically after being constructed. - /// - //////////////////////////////////////////////////////////// - public Clock() : base(sfClock_create()) { } - - //////////////////////////////////////////////////////////// - /// - /// Handle the destruction of the object - /// - /// Is the GC disposing the object, or is it an explicit call ? - //////////////////////////////////////////////////////////// - protected override void Destroy(bool disposing) => sfClock_destroy(CPointer); - - //////////////////////////////////////////////////////////// - /// - /// Gets the time elapsed since the last call to Restart - /// (or the construction of the instance if Restart - /// has not been called). - /// - //////////////////////////////////////////////////////////// - public Time ElapsedTime => sfClock_getElapsedTime(CPointer); - - //////////////////////////////////////////////////////////// - /// - /// Check whether the clock is running - /// - //////////////////////////////////////////////////////////// - public bool IsRunning => sfClock_isRunning(CPointer); - - //////////////////////////////////////////////////////////// - /// - /// Start the clock - /// - //////////////////////////////////////////////////////////// - public void Start() => sfClock_start(CPointer); - - //////////////////////////////////////////////////////////// - /// - /// Stop the clock - /// - //////////////////////////////////////////////////////////// - public void Stop() => sfClock_stop(CPointer); - - //////////////////////////////////////////////////////////// - /// - /// This function puts the time counter back to zero. - /// - /// Time elapsed since the clock was started. - //////////////////////////////////////////////////////////// - public Time Restart() => sfClock_restart(CPointer); - - //////////////////////////////////////////////////////////// - /// - /// Reset the clock - /// - /// This function puts the time counter back to zero, returns - /// the elapsed time, and leaves the clock in a paused state. - /// - //////////////////////////////////////////////////////////// - public Time Reset() => sfClock_reset(CPointer); - - #region Imports - [DllImport(CSFML.System, CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] - private static extern IntPtr sfClock_create(); - - [DllImport(CSFML.System, CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] - private static extern void sfClock_destroy(IntPtr cPointer); - - [DllImport(CSFML.System, CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] - private static extern Time sfClock_getElapsedTime(IntPtr clock); - - [DllImport(CSFML.System, CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] - [return: MarshalAs(UnmanagedType.I1)] - private static extern bool sfClock_isRunning(IntPtr clock); - - [DllImport(CSFML.System, CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] - private static extern void sfClock_start(IntPtr clock); - - [DllImport(CSFML.System, CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] - private static extern void sfClock_stop(IntPtr clock); - - [DllImport(CSFML.System, CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] - private static extern Time sfClock_restart(IntPtr clock); - - [DllImport(CSFML.System, CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] - private static extern Time sfClock_reset(IntPtr clock); - #endregion - } + public Clock() : base(sfClock_create()) { } + + //////////////////////////////////////////////////////////// + /// + /// Handle the destruction of the object + /// + /// Is the GC disposing the object, or is it an explicit call ? + //////////////////////////////////////////////////////////// + protected override void Destroy(bool disposing) => sfClock_destroy(CPointer); + + //////////////////////////////////////////////////////////// + /// + /// Gets the time elapsed since the last call to Restart + /// (or the construction of the instance if Restart + /// has not been called). + /// + //////////////////////////////////////////////////////////// + public Time ElapsedTime => sfClock_getElapsedTime(CPointer); + + //////////////////////////////////////////////////////////// + /// + /// Check whether the clock is running + /// + //////////////////////////////////////////////////////////// + public bool IsRunning => sfClock_isRunning(CPointer); + + //////////////////////////////////////////////////////////// + /// + /// Start the clock + /// + //////////////////////////////////////////////////////////// + public void Start() => sfClock_start(CPointer); + + //////////////////////////////////////////////////////////// + /// + /// Stop the clock + /// + //////////////////////////////////////////////////////////// + public void Stop() => sfClock_stop(CPointer); + + //////////////////////////////////////////////////////////// + /// + /// This function puts the time counter back to zero. + /// + /// Time elapsed since the clock was started. + //////////////////////////////////////////////////////////// + public Time Restart() => sfClock_restart(CPointer); + + //////////////////////////////////////////////////////////// + /// + /// Reset the clock + /// + /// This function puts the time counter back to zero, returns + /// the elapsed time, and leaves the clock in a paused state. + /// + //////////////////////////////////////////////////////////// + public Time Reset() => sfClock_reset(CPointer); + + #region Imports + [DllImport(CSFML.System, CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] + private static extern IntPtr sfClock_create(); + + [DllImport(CSFML.System, CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] + private static extern void sfClock_destroy(IntPtr cPointer); + + [DllImport(CSFML.System, CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] + private static extern Time sfClock_getElapsedTime(IntPtr clock); + + [DllImport(CSFML.System, CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] + [return: MarshalAs(UnmanagedType.I1)] + private static extern bool sfClock_isRunning(IntPtr clock); + + [DllImport(CSFML.System, CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] + private static extern void sfClock_start(IntPtr clock); + + [DllImport(CSFML.System, CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] + private static extern void sfClock_stop(IntPtr clock); + + [DllImport(CSFML.System, CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] + private static extern Time sfClock_restart(IntPtr clock); + + [DllImport(CSFML.System, CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] + private static extern Time sfClock_reset(IntPtr clock); + #endregion } diff --git a/src/SFML.System/LoadingFailedException.cs b/src/SFML.System/LoadingFailedException.cs index ebcb4b9f..f79516b8 100644 --- a/src/SFML.System/LoadingFailedException.cs +++ b/src/SFML.System/LoadingFailedException.cs @@ -1,80 +1,79 @@ using System; using System.Runtime.Serialization; -namespace SFML.System +namespace SFML.System; + +//////////////////////////////////////////////////////////// +/// +/// Exception thrown by SFML whenever loading a resource fails +/// +//////////////////////////////////////////////////////////// +[Serializable] +public class LoadingFailedException : Exception { //////////////////////////////////////////////////////////// /// - /// Exception thrown by SFML whenever loading a resource fails + /// Default constructor (unknown error) /// //////////////////////////////////////////////////////////// - [Serializable] - public class LoadingFailedException : Exception - { - //////////////////////////////////////////////////////////// - /// - /// Default constructor (unknown error) - /// - //////////////////////////////////////////////////////////// - public LoadingFailedException() : base("Failed to load a resource") { } + public LoadingFailedException() : base("Failed to load a resource") { } - //////////////////////////////////////////////////////////// - /// - /// Failure to load a resource from memory - /// - /// Name of the resource - //////////////////////////////////////////////////////////// - public LoadingFailedException(string resourceName) : base($"Failed to load {resourceName} from memory") - { - } + //////////////////////////////////////////////////////////// + /// + /// Failure to load a resource from memory + /// + /// Name of the resource + //////////////////////////////////////////////////////////// + public LoadingFailedException(string resourceName) : base($"Failed to load {resourceName} from memory") + { + } - //////////////////////////////////////////////////////////// - /// - /// Failure to load a resource from memory - /// - /// Name of the resource - /// Exception which is the cause of the current exception - //////////////////////////////////////////////////////////// - public LoadingFailedException(string resourceName, Exception innerException) : - base($"Failed to load {resourceName} from memory", innerException) - { - } + //////////////////////////////////////////////////////////// + /// + /// Failure to load a resource from memory + /// + /// Name of the resource + /// Exception which is the cause of the current exception + //////////////////////////////////////////////////////////// + public LoadingFailedException(string resourceName, Exception innerException) : + base($"Failed to load {resourceName} from memory", innerException) + { + } - //////////////////////////////////////////////////////////// - /// - /// Failure to load a resource from a file - /// - /// Name of the resource - /// Path of the file - //////////////////////////////////////////////////////////// - public LoadingFailedException(string resourceName, string filename) : - base($"Failed to load {resourceName} from file {filename}") - { - } + //////////////////////////////////////////////////////////// + /// + /// Failure to load a resource from a file + /// + /// Name of the resource + /// Path of the file + //////////////////////////////////////////////////////////// + public LoadingFailedException(string resourceName, string filename) : + base($"Failed to load {resourceName} from file {filename}") + { + } - //////////////////////////////////////////////////////////// - /// - /// Failure to load a resource from a file - /// - /// Name of the resource - /// Path of the file - /// Exception which is the cause of the current exception - //////////////////////////////////////////////////////////// - public LoadingFailedException(string resourceName, string filename, Exception innerException) : - base($"Failed to load {resourceName} from file {filename}", innerException) - { - } + //////////////////////////////////////////////////////////// + /// + /// Failure to load a resource from a file + /// + /// Name of the resource + /// Path of the file + /// Exception which is the cause of the current exception + //////////////////////////////////////////////////////////// + public LoadingFailedException(string resourceName, string filename, Exception innerException) : + base($"Failed to load {resourceName} from file {filename}", innerException) + { + } - //////////////////////////////////////////////////////////// - /// - /// Initialize an instance of the exception with serialized data - /// - /// Serialized data - /// Contextual information - //////////////////////////////////////////////////////////// - public LoadingFailedException(SerializationInfo info, StreamingContext context) : - base(info, context) - { - } + //////////////////////////////////////////////////////////// + /// + /// Initialize an instance of the exception with serialized data + /// + /// Serialized data + /// Contextual information + //////////////////////////////////////////////////////////// + public LoadingFailedException(SerializationInfo info, StreamingContext context) : + base(info, context) + { } } diff --git a/src/SFML.System/ObjectBase.cs b/src/SFML.System/ObjectBase.cs index 3d0e3562..3f274956 100644 --- a/src/SFML.System/ObjectBase.cs +++ b/src/SFML.System/ObjectBase.cs @@ -1,103 +1,99 @@ using System; -namespace SFML +namespace SFML; + +//////////////////////////////////////////////////////////// +/// +/// The ObjectBase class is an abstract base for every +/// SFML object. It's meant for internal use only +/// +//////////////////////////////////////////////////////////// +public abstract class ObjectBase : IDisposable { //////////////////////////////////////////////////////////// /// - /// The ObjectBase class is an abstract base for every - /// SFML object. It's meant for internal use only + /// Construct the object from a pointer to the C library object /// + /// Internal pointer to the object in the C libraries //////////////////////////////////////////////////////////// - public abstract class ObjectBase : IDisposable - { - //////////////////////////////////////////////////////////// - /// - /// Construct the object from a pointer to the C library object - /// - /// Internal pointer to the object in the C libraries - //////////////////////////////////////////////////////////// - public ObjectBase(IntPtr cPointer) => _cPointer = cPointer; + protected ObjectBase(IntPtr cPointer) => _cPointer = cPointer; - //////////////////////////////////////////////////////////// - /// - /// Dispose the object - /// - //////////////////////////////////////////////////////////// - ~ObjectBase() - { - Dispose(false); - } + //////////////////////////////////////////////////////////// + /// + /// Dispose the object + /// + //////////////////////////////////////////////////////////// + ~ObjectBase() => Dispose(false); - //////////////////////////////////////////////////////////// - /// - /// Access to the internal pointer of the object. - /// For internal use only - /// - /// Attempting to get the value while is true will throw an . - /// - //////////////////////////////////////////////////////////// - public IntPtr CPointer + //////////////////////////////////////////////////////////// + /// + /// Access to the internal pointer of the object. + /// For internal use only + /// + /// Attempting to get the value while is true will throw an . + /// + //////////////////////////////////////////////////////////// + public IntPtr CPointer + { + get { - get + if (_cPointer == IntPtr.Zero) { - if (_cPointer == IntPtr.Zero) - { - throw new ObjectDisposedException($"This {GetType().Name} instance has been disposed and should not be used."); - } - - return _cPointer; + throw new ObjectDisposedException($"This {GetType().Name} instance has been disposed and should not be used."); } - protected set => _cPointer = value; + + return _cPointer; } + protected set => _cPointer = value; + } - //////////////////////////////////////////////////////////// - /// - /// Returns true if the object is in an invalid state, false otherwise. - /// For internal use only - /// - //////////////////////////////////////////////////////////// - public bool IsInvalid => _cPointer == IntPtr.Zero; + //////////////////////////////////////////////////////////// + /// + /// Returns true if the object is in an invalid state, false otherwise. + /// For internal use only + /// + //////////////////////////////////////////////////////////// + public bool IsInvalid => _cPointer == IntPtr.Zero; - //////////////////////////////////////////////////////////// - /// - /// Explicitly dispose the object - /// - //////////////////////////////////////////////////////////// - public void Dispose() - { - Dispose(true); - GC.SuppressFinalize(this); - } + //////////////////////////////////////////////////////////// + /// + /// Explicitly dispose the object + /// + //////////////////////////////////////////////////////////// + public void Dispose() + { + Dispose(true); + GC.SuppressFinalize(this); + } - //////////////////////////////////////////////////////////// - /// - /// Destroy the object - /// - /// Is the GC disposing the object, or is it an explicit call? - //////////////////////////////////////////////////////////// - private void Dispose(bool disposing) + //////////////////////////////////////////////////////////// + /// + /// Destroy the object + /// + /// Is the GC disposing the object, or is it an explicit call? + //////////////////////////////////////////////////////////// + private void Dispose(bool disposing) + { + if (_cPointer != IntPtr.Zero) { - if (_cPointer != IntPtr.Zero) - { - Destroy(disposing); - _cPointer = IntPtr.Zero; - } + Destroy(disposing); + _cPointer = IntPtr.Zero; } + } - //////////////////////////////////////////////////////////// - /// - /// Destroy the object (implementation is left to each derived class) - /// - /// Is the GC disposing the object, or is it an explicit call? - //////////////////////////////////////////////////////////// - protected abstract void Destroy(bool disposing); + //////////////////////////////////////////////////////////// + /// + /// Destroy the object (implementation is left to each derived class) + /// + /// Is the GC disposing the object, or is it an explicit call? + //////////////////////////////////////////////////////////// + protected abstract void Destroy(bool disposing); - /// - /// Create a string that can be used in overrides to describe disposed objects - /// - /// A string representation of the disposed object - protected string MakeDisposedObjectString() => $"[{GetType().Name} (disposed)]"; + /// + /// Create a string that can be used in overrides to describe disposed objects + /// + /// A string representation of the disposed object + protected string MakeDisposedObjectString() => $"[{GetType().Name} (disposed)]"; - private IntPtr _cPointer = IntPtr.Zero; - } + private IntPtr _cPointer = IntPtr.Zero; } diff --git a/src/SFML.System/SharedLibName.cs b/src/SFML.System/SharedLibName.cs index d07dcb3a..dc9ded8c 100644 --- a/src/SFML.System/SharedLibName.cs +++ b/src/SFML.System/SharedLibName.cs @@ -1,18 +1,17 @@ -namespace SFML.System +namespace SFML.System; + +/// CSFML +public static class CSFML { - /// CSFML - public static class CSFML - { - /// CSFML Audio Lib Name - public const string Audio = "csfml-audio"; + /// CSFML Audio Lib Name + public const string Audio = "csfml-audio"; - /// CSFML Graphics Lib Name - public const string Graphics = "csfml-graphics"; + /// CSFML Graphics Lib Name + public const string Graphics = "csfml-graphics"; - /// CSFML System Lib Name - public const string System = "csfml-system"; + /// CSFML System Lib Name + public const string System = "csfml-system"; - /// CSFML Window Lib Name - public const string Window = "csfml-window"; - } + /// CSFML Window Lib Name + public const string Window = "csfml-window"; } diff --git a/src/SFML.System/StreamAdaptor.cs b/src/SFML.System/StreamAdaptor.cs index 3dddd884..ce98e167 100644 --- a/src/SFML.System/StreamAdaptor.cs +++ b/src/SFML.System/StreamAdaptor.cs @@ -2,189 +2,185 @@ using System.IO; using System.Runtime.InteropServices; -namespace SFML.System +namespace SFML.System; + +//////////////////////////////////////////////////////////// +/// +/// Structure that contains InputStream callbacks +/// (directly maps to a CSFML sfInputStream) +/// +//////////////////////////////////////////////////////////// +[StructLayout(LayoutKind.Sequential)] +public struct InputStream { //////////////////////////////////////////////////////////// /// - /// Structure that contains InputStream callbacks - /// (directly maps to a CSFML sfInputStream) + /// Type of callback to read data from the current stream /// //////////////////////////////////////////////////////////// - [StructLayout(LayoutKind.Sequential)] - public struct InputStream + [UnmanagedFunctionPointer(CallingConvention.Cdecl)] + public delegate long ReadCallbackType(IntPtr data, UIntPtr size, IntPtr userData); + + //////////////////////////////////////////////////////////// + /// + /// Type of callback to seek the current stream's position + /// + //////////////////////////////////////////////////////////// + [UnmanagedFunctionPointer(CallingConvention.Cdecl)] + public delegate long SeekCallbackType(UIntPtr position, IntPtr userData); + + //////////////////////////////////////////////////////////// + /// + /// Type of callback to return the current stream's position + /// + //////////////////////////////////////////////////////////// + [UnmanagedFunctionPointer(CallingConvention.Cdecl)] + public delegate long TellCallbackType(IntPtr userData); + + //////////////////////////////////////////////////////////// + /// + /// Type of callback to return the current stream's size + /// + //////////////////////////////////////////////////////////// + [UnmanagedFunctionPointer(CallingConvention.Cdecl)] + public delegate long GetSizeCallbackType(IntPtr userData); + + //////////////////////////////////////////////////////////// + /// + /// Function that is called to read data from the stream + /// + //////////////////////////////////////////////////////////// + public ReadCallbackType Read; + + //////////////////////////////////////////////////////////// + /// + /// Function that is called to seek the stream + /// + //////////////////////////////////////////////////////////// + public SeekCallbackType Seek; + + //////////////////////////////////////////////////////////// + /// + /// Function that is called to return the position + /// + //////////////////////////////////////////////////////////// + public TellCallbackType Tell; + + //////////////////////////////////////////////////////////// + /// + /// Function that is called to return the size + /// + //////////////////////////////////////////////////////////// + public GetSizeCallbackType GetSize; +} + +//////////////////////////////////////////////////////////// +/// +/// Adapts a System.IO.Stream to be usable as a SFML InputStream +/// +//////////////////////////////////////////////////////////// +public class StreamAdaptor : IDisposable +{ + //////////////////////////////////////////////////////////// + /// + /// Construct from a System.IO.Stream + /// + /// Stream to adapt + //////////////////////////////////////////////////////////// + public StreamAdaptor(Stream stream) + { + _stream = stream; + + _inputStream = new InputStream + { + Read = new InputStream.ReadCallbackType(Read), + Seek = new InputStream.SeekCallbackType(Seek), + Tell = new InputStream.TellCallbackType(Tell), + GetSize = new InputStream.GetSizeCallbackType(GetSize) + }; + + InputStreamPtr = Marshal.AllocHGlobal(Marshal.SizeOf(_inputStream)); + Marshal.StructureToPtr(_inputStream, InputStreamPtr, false); + } + + //////////////////////////////////////////////////////////// + /// + /// Dispose the object + /// + //////////////////////////////////////////////////////////// + ~StreamAdaptor() => Dispose(false); + + //////////////////////////////////////////////////////////// + /// + /// The pointer to the CSFML InputStream structure + /// + //////////////////////////////////////////////////////////// + public IntPtr InputStreamPtr { get; } + + //////////////////////////////////////////////////////////// + /// + /// Explicitly dispose the object + /// + //////////////////////////////////////////////////////////// + public void Dispose() { - //////////////////////////////////////////////////////////// - /// - /// Type of callback to read data from the current stream - /// - //////////////////////////////////////////////////////////// - [UnmanagedFunctionPointer(CallingConvention.Cdecl)] - public delegate long ReadCallbackType(IntPtr data, UIntPtr size, IntPtr userData); - - //////////////////////////////////////////////////////////// - /// - /// Type of callback to seek the current stream's position - /// - //////////////////////////////////////////////////////////// - [UnmanagedFunctionPointer(CallingConvention.Cdecl)] - public delegate long SeekCallbackType(UIntPtr position, IntPtr userData); - - //////////////////////////////////////////////////////////// - /// - /// Type of callback to return the current stream's position - /// - //////////////////////////////////////////////////////////// - [UnmanagedFunctionPointer(CallingConvention.Cdecl)] - public delegate long TellCallbackType(IntPtr userData); - - //////////////////////////////////////////////////////////// - /// - /// Type of callback to return the current stream's size - /// - //////////////////////////////////////////////////////////// - [UnmanagedFunctionPointer(CallingConvention.Cdecl)] - public delegate long GetSizeCallbackType(IntPtr userData); - - //////////////////////////////////////////////////////////// - /// - /// Function that is called to read data from the stream - /// - //////////////////////////////////////////////////////////// - public ReadCallbackType Read; - - //////////////////////////////////////////////////////////// - /// - /// Function that is called to seek the stream - /// - //////////////////////////////////////////////////////////// - public SeekCallbackType Seek; - - //////////////////////////////////////////////////////////// - /// - /// Function that is called to return the position - /// - //////////////////////////////////////////////////////////// - public TellCallbackType Tell; - - //////////////////////////////////////////////////////////// - /// - /// Function that is called to return the size - /// - //////////////////////////////////////////////////////////// - public GetSizeCallbackType GetSize; + Dispose(true); + GC.SuppressFinalize(this); } //////////////////////////////////////////////////////////// /// - /// Adapts a System.IO.Stream to be usable as a SFML InputStream + /// Destroy the object /// + /// Is the GC disposing the object, or is it an explicit call ? + //////////////////////////////////////////////////////////// + private void Dispose(bool disposing) => Marshal.FreeHGlobal(InputStreamPtr); + //////////////////////////////////////////////////////////// - public class StreamAdaptor : IDisposable + /// + /// Called to read from the stream + /// + /// Where to copy the read bytes + /// Size to read, in bytes + /// User data -- unused + /// Number of bytes read + //////////////////////////////////////////////////////////// + private long Read(IntPtr data, UIntPtr size, IntPtr userData) { - //////////////////////////////////////////////////////////// - /// - /// Construct from a System.IO.Stream - /// - /// Stream to adapt - //////////////////////////////////////////////////////////// - public StreamAdaptor(Stream stream) - { - _stream = stream; - - _inputStream = new InputStream - { - Read = new InputStream.ReadCallbackType(Read), - Seek = new InputStream.SeekCallbackType(Seek), - Tell = new InputStream.TellCallbackType(Tell), - GetSize = new InputStream.GetSizeCallbackType(GetSize) - }; - - InputStreamPtr = Marshal.AllocHGlobal(Marshal.SizeOf(_inputStream)); - Marshal.StructureToPtr(_inputStream, InputStreamPtr, false); - } - - //////////////////////////////////////////////////////////// - /// - /// Dispose the object - /// - //////////////////////////////////////////////////////////// - ~StreamAdaptor() - { - Dispose(false); - } - - //////////////////////////////////////////////////////////// - /// - /// The pointer to the CSFML InputStream structure - /// - //////////////////////////////////////////////////////////// - public IntPtr InputStreamPtr { get; } - - //////////////////////////////////////////////////////////// - /// - /// Explicitly dispose the object - /// - //////////////////////////////////////////////////////////// - public void Dispose() - { - Dispose(true); - GC.SuppressFinalize(this); - } - - //////////////////////////////////////////////////////////// - /// - /// Destroy the object - /// - /// Is the GC disposing the object, or is it an explicit call ? - //////////////////////////////////////////////////////////// - private void Dispose(bool disposing) => Marshal.FreeHGlobal(InputStreamPtr); - - //////////////////////////////////////////////////////////// - /// - /// Called to read from the stream - /// - /// Where to copy the read bytes - /// Size to read, in bytes - /// User data -- unused - /// Number of bytes read - //////////////////////////////////////////////////////////// - private long Read(IntPtr data, UIntPtr size, IntPtr userData) - { - var buffer = new byte[(int)size]; - var count = _stream.Read(buffer, 0, (int)size); - Marshal.Copy(buffer, 0, data, count); - return count; - } - - //////////////////////////////////////////////////////////// - /// - /// Called to set the read position in the stream - /// - /// New read position - /// User data -- unused - /// Actual position - //////////////////////////////////////////////////////////// - private long Seek(UIntPtr position, IntPtr userData) => _stream.Seek((long)position, SeekOrigin.Begin); - - //////////////////////////////////////////////////////////// - /// - /// Get the current read position in the stream - /// - /// User data -- unused - /// Current position in the stream - //////////////////////////////////////////////////////////// - private long Tell(IntPtr userData) => _stream.Position; - - //////////////////////////////////////////////////////////// - /// - /// Called to get the total size of the stream - /// - /// User data -- unused - /// Number of bytes in the stream - //////////////////////////////////////////////////////////// - private long GetSize(IntPtr userData) => _stream.Length; - - private readonly Stream _stream; - private InputStream _inputStream; + var buffer = new byte[(int)size]; + var count = _stream.Read(buffer, 0, (int)size); + Marshal.Copy(buffer, 0, data, count); + return count; } + + //////////////////////////////////////////////////////////// + /// + /// Called to set the read position in the stream + /// + /// New read position + /// User data -- unused + /// Actual position + //////////////////////////////////////////////////////////// + private long Seek(UIntPtr position, IntPtr userData) => _stream.Seek((long)position, SeekOrigin.Begin); + + //////////////////////////////////////////////////////////// + /// + /// Get the current read position in the stream + /// + /// User data -- unused + /// Current position in the stream + //////////////////////////////////////////////////////////// + private long Tell(IntPtr userData) => _stream.Position; + + //////////////////////////////////////////////////////////// + /// + /// Called to get the total size of the stream + /// + /// User data -- unused + /// Number of bytes in the stream + //////////////////////////////////////////////////////////// + private long GetSize(IntPtr userData) => _stream.Length; + + private readonly Stream _stream; + private InputStream _inputStream; } diff --git a/src/SFML.System/Time.cs b/src/SFML.System/Time.cs index 7c2a832a..ca109835 100644 --- a/src/SFML.System/Time.cs +++ b/src/SFML.System/Time.cs @@ -2,265 +2,264 @@ using System.Runtime.InteropServices; using System.Security; -namespace SFML.System +namespace SFML.System; + +//////////////////////////////////////////////////////////// +/// +/// A Time value for interfacing with SFML +/// +/// +/// Using while working within managed code is best. +/// In most cases, is only needed when calling into unmanaged code. +/// Implicit casts from to +/// allow s to be used for most SFML methods. +/// +//////////////////////////////////////////////////////////// +[StructLayout(LayoutKind.Sequential)] +public readonly struct Time : IEquatable