[2.0] Sunday Sprint (#260)
* Add SourceLink (closes #213) * Begin targeting Preview 2 * Use same structs for GLFW Image Data (closes #139) * Fix deterministic builds * Add framebuffer size (closes #261) * Add nullability (closes #39) * Add position to click events (closes #140) * Remove the LastKey enumerant (closes #259) * Add measures to ensure that window visibility is correct (closes #66) * First review fix * Second review fix * Update src/Input/Silk.NET.Input.Glfw/ReadOnlyListEnumerator.cs * Update src/Core/Silk.NET.Core/Miscellaneous/RawImage.cs Co-authored-by: HurricanKai <kai.jellinghaus1@gmail.com> Co-authored-by: HurricanKai <kai.jellinghaus1@gmail.com>
This commit is contained in:
Родитель
1d0a824124
Коммит
fa2c8b8345
|
@ -20,7 +20,7 @@ jobs:
|
|||
- name: Test
|
||||
run: dotnet test --verbosity normal
|
||||
- name: Pack
|
||||
run: dotnet pack --configuration Release --version-suffix build$GITHUB_RUN_NUMBER.0
|
||||
run: dotnet pack --configuration Release --version-suffix build$GITHUB_RUN_NUMBER.0 -p:ContinuousIntegrationBuild=true
|
||||
- name: Setup NuGet
|
||||
uses: nuget/setup-nuget@v1
|
||||
with:
|
||||
|
|
|
@ -19,7 +19,7 @@ jobs:
|
|||
- name: Install dependencies
|
||||
run: dotnet restore
|
||||
- name: Pack
|
||||
run: dotnet pack --configuration Release
|
||||
run: dotnet pack --configuration Release -p:ContinuousIntegrationBuild=true
|
||||
- name: Test
|
||||
run: dotnet test --no-restore --verbosity normal
|
||||
- name: Push to NuGet
|
||||
|
|
|
@ -179,6 +179,7 @@ PublishScripts/
|
|||
|
||||
# NuGet Packages
|
||||
*.nupkg
|
||||
*.snupkg
|
||||
# The packages folder can be ignored because of Package Restore
|
||||
**/[Pp]ackages/*
|
||||
# except build/, which is used as an MSBuild target.
|
||||
|
|
|
@ -12,9 +12,19 @@
|
|||
<RepositoryUrl>https://github.com/Ultz/Silk.NET</RepositoryUrl>
|
||||
<RepositoryType>Git</RepositoryType>
|
||||
<VersionPrefix>2.0.0</VersionPrefix>
|
||||
<VersionSuffix Condition="'$(VersionSuffix)' == ''">preview</VersionSuffix>
|
||||
<VersionSuffix Condition="'$(VersionSuffix)' == ''">preview2</VersionSuffix>
|
||||
<Description>
|
||||
Silk.NET is a high-speed, advanced library, providing bindings to popular low-level APIs such as OpenGL, OpenCL, OpenAL, GLFW, and Vulkan.
|
||||
</Description>
|
||||
</PropertyGroup>
|
||||
<!-- SourceLink -->
|
||||
<PropertyGroup>
|
||||
<PublishRepositoryUrl>true</PublishRepositoryUrl>
|
||||
<EmbedUntrackedSources>true</EmbedUntrackedSources>
|
||||
<IncludeSymbols>true</IncludeSymbols>
|
||||
<SymbolPackageFormat>snupkg</SymbolPackageFormat>
|
||||
</PropertyGroup>
|
||||
<ItemGroup>
|
||||
<PackageReference Include="Microsoft.SourceLink.GitHub" Version="1.0.0" PrivateAssets="All"/>
|
||||
</ItemGroup>
|
||||
</Project>
|
||||
|
|
|
@ -0,0 +1,87 @@
|
|||
// This file is part of Silk.NET.
|
||||
//
|
||||
// You may modify and distribute Silk.NET under the terms
|
||||
// of the MIT license. See the LICENSE file for details.
|
||||
|
||||
using System;
|
||||
using System.Linq;
|
||||
|
||||
namespace Silk.NET.Core
|
||||
{
|
||||
/// <summary>
|
||||
/// Represents loaded, uncompressed, processed image data.
|
||||
/// </summary>
|
||||
public readonly struct RawImage : IEquatable<RawImage>
|
||||
{
|
||||
/// <summary>
|
||||
/// Creates a <see cref="RawImage"/> given pixel data and pixel dimensions.
|
||||
/// </summary>
|
||||
/// <param name="width">The width of the image.</param>
|
||||
/// <param name="height">The height of the image.</param>
|
||||
/// <param name="rgbaPixels">The image daqta.</param>
|
||||
public RawImage(int width, int height, Memory<byte> rgbaPixels)
|
||||
{
|
||||
Pixels = rgbaPixels;
|
||||
Width = width;
|
||||
Height = height;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// The width of the image in pixels
|
||||
/// </summary>
|
||||
public int Width { get; }
|
||||
/// <summary>
|
||||
/// The height of the image in pixels.
|
||||
/// </summary>
|
||||
public int Height { get; }
|
||||
|
||||
/// <summary>
|
||||
/// The image data.
|
||||
/// </summary>
|
||||
public Memory<byte> Pixels { get; }
|
||||
|
||||
/// <summary>
|
||||
/// Checks whether the two given <see cref="RawImage"/>s are equal.
|
||||
/// </summary>
|
||||
/// <param name="left">The first raw image.</param>
|
||||
/// <param name="right">The second raw image to compare the first against.</param>
|
||||
/// <returns>True if they are equal, false otherwise.</returns>
|
||||
/// <remarks>
|
||||
/// This does not check whether the byte arrays are equal, only whether their references are the same.
|
||||
/// </remarks>
|
||||
public static bool operator ==(RawImage left, RawImage right) => left.Equals(right);
|
||||
|
||||
/// <summary>
|
||||
/// Checks whether the two given <see cref="RawImage"/>s are not equal.
|
||||
/// </summary>
|
||||
/// <param name="left">The first raw image.</param>
|
||||
/// <param name="right">The second raw image to compare the first against.</param>
|
||||
/// <returns>True if they are not equal, false otherwise.</returns>
|
||||
/// <remarks>
|
||||
/// This does not check whether the byte arrays are equal, only whether their references are the same.
|
||||
/// </remarks>
|
||||
public static bool operator !=(RawImage left, RawImage right) => !(left == right);
|
||||
|
||||
/// <summary>
|
||||
/// Checks whether the given <see cref="RawImage"/> is equal to this one.
|
||||
/// </summary>
|
||||
/// <param name="other">The raw image to compare this raw image against.</param>
|
||||
/// <returns>True if they are equal, false otherwise.</returns>
|
||||
/// <remarks>
|
||||
/// This does not check whether the byte arrays have equal, only whether their references are the same.
|
||||
/// </remarks>
|
||||
public bool Equals(RawImage other)
|
||||
{
|
||||
return Width == other.Width && Height == other.Height && Equals(Pixels, other.Pixels);
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
public override bool Equals(object obj)
|
||||
{
|
||||
return obj is RawImage other && Equals(other);
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
public override int GetHashCode() => HashCode.Combine(Width, Height, Pixels);
|
||||
}
|
||||
}
|
|
@ -7,6 +7,7 @@
|
|||
</PropertyGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<PackageReference Include="Microsoft.Bcl.HashCode" Version="1.1.0" />
|
||||
<PackageReference Include="Microsoft.CSharp" Version="4.7.0" />
|
||||
<PackageReference Include="System.Memory" Version="4.5.3" />
|
||||
<PackageReference Include="System.Reflection.Emit" Version="4.7.0" />
|
||||
|
|
|
@ -0,0 +1,2 @@
|
|||
<wpf:ResourceDictionary xml:space="preserve" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" xmlns:s="clr-namespace:System;assembly=mscorlib" xmlns:ss="urn:shemas-jetbrains-com:settings-storage-xaml" xmlns:wpf="http://schemas.microsoft.com/winfx/2006/xaml/presentation">
|
||||
<s:Boolean x:Key="/Default/CodeInspection/NamespaceProvider/NamespaceFoldersToSkip/=miscellaneous/@EntryIndexedValue">True</s:Boolean></wpf:ResourceDictionary>
|
|
@ -1,11 +0,0 @@
|
|||
// This file is part of Silk.NET.
|
||||
//
|
||||
// You may modify and distribute Silk.NET under the terms
|
||||
// of the MIT license. See the LICENSE file for details.
|
||||
|
||||
using Silk.NET.Windowing;
|
||||
|
||||
namespace Silk.NET.Input
|
||||
{
|
||||
public delegate bool CustomInputContextCreationCallback(IView view, out IInputContext context);
|
||||
}
|
|
@ -618,11 +618,6 @@ namespace Silk.NET.Input
|
|||
/// <summary>
|
||||
/// The menu key.
|
||||
/// </summary>
|
||||
Menu = 348,
|
||||
|
||||
/// <summary>
|
||||
/// The last valid key in this enum.
|
||||
/// </summary>
|
||||
LastKey = Menu
|
||||
Menu = 348
|
||||
}
|
||||
}
|
||||
|
|
|
@ -3,6 +3,8 @@
|
|||
// You may modify and distribute Silk.NET under the terms
|
||||
// of the MIT license. See the LICENSE file for details.
|
||||
|
||||
using Silk.NET.Core;
|
||||
|
||||
namespace Silk.NET.Input
|
||||
{
|
||||
/// <summary>
|
||||
|
@ -47,22 +49,6 @@ namespace Silk.NET.Input
|
|||
/// </remarks>
|
||||
int HotspotY { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Width of the cursor in pixels.
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// Is only used if <see cref="Type"/> is <see cref="CursorType.Custom"/>.
|
||||
/// </remarks>
|
||||
int Width { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Height of the cursor in pixels.
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// Is only used if <see cref="Type"/> is <see cref="CursorType.Custom"/>.
|
||||
/// </remarks>
|
||||
int Height { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Image data for the cursor.
|
||||
/// </summary>
|
||||
|
@ -70,7 +56,7 @@ namespace Silk.NET.Input
|
|||
/// The image MUST be in 32-bit RGBA, non-premultiplied, and in little-endian format.
|
||||
/// Is only used if <see cref="Type"/> is <see cref="CursorType.Custom"/>.
|
||||
/// </remarks>
|
||||
byte[] Pixels { get; set; }
|
||||
RawImage Image { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Checks whether or not a specific <see cref="CursorMode"/> is supported.
|
||||
|
|
|
@ -44,7 +44,7 @@ namespace Silk.NET.Input
|
|||
/// <remarks>
|
||||
/// This event is only called when the button is first pressed, and not every frame where the button is still pressed.
|
||||
/// </remarks>
|
||||
event Action<IGamepad, Button> ButtonDown;
|
||||
event Action<IGamepad, Button>? ButtonDown;
|
||||
|
||||
/// <summary>
|
||||
/// Called when a button is released.
|
||||
|
@ -52,16 +52,16 @@ namespace Silk.NET.Input
|
|||
/// <remarks>
|
||||
/// This event is only called when the button is first released, and not every frame where the button is still released.
|
||||
/// </remarks>
|
||||
event Action<IGamepad, Button> ButtonUp;
|
||||
event Action<IGamepad, Button>? ButtonUp;
|
||||
|
||||
/// <summary>
|
||||
/// Called when a thumbstick is moved.
|
||||
/// </summary>
|
||||
event Action<IGamepad, Thumbstick> ThumbstickMoved;
|
||||
event Action<IGamepad, Thumbstick>? ThumbstickMoved;
|
||||
|
||||
/// <summary>
|
||||
/// Called when a trigger is moved.
|
||||
/// </summary>
|
||||
event Action<IGamepad, Trigger> TriggerMoved;
|
||||
event Action<IGamepad, Trigger>? TriggerMoved;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -58,6 +58,6 @@ namespace Silk.NET.Input
|
|||
/// <summary>
|
||||
/// Called when the connection status of a device changes.
|
||||
/// </summary>
|
||||
event Action<IInputDevice, bool> ConnectionChanged;
|
||||
event Action<IInputDevice, bool>? ConnectionChanged;
|
||||
}
|
||||
}
|
|
@ -39,7 +39,7 @@ namespace Silk.NET.Input
|
|||
/// <remarks>
|
||||
/// This event is only called when the button is first pressed, and not every frame where the button is still pressed.
|
||||
/// </remarks>
|
||||
event Action<IJoystick, Button> ButtonDown;
|
||||
event Action<IJoystick, Button>? ButtonDown;
|
||||
|
||||
/// <summary>
|
||||
/// Called when a button on this joystick is released.
|
||||
|
@ -47,16 +47,16 @@ namespace Silk.NET.Input
|
|||
/// <remarks>
|
||||
/// This event is only called when the button is first released, and not every frame where the button is still released.
|
||||
/// </remarks>
|
||||
event Action<IJoystick, Button> ButtonUp;
|
||||
event Action<IJoystick, Button>? ButtonUp;
|
||||
|
||||
/// <summary>
|
||||
/// Called when an axis on this joystick is moved.
|
||||
/// </summary>
|
||||
event Action<IJoystick, Axis> AxisMoved;
|
||||
event Action<IJoystick, Axis>? AxisMoved;
|
||||
|
||||
/// <summary>
|
||||
/// Called when a hat on this joystick is moved.
|
||||
/// </summary>
|
||||
event Action<IJoystick, Hat> HatMoved;
|
||||
event Action<IJoystick, Hat>? HatMoved;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -28,16 +28,16 @@ namespace Silk.NET.Input
|
|||
/// <summary>
|
||||
/// Called when a key is pressed.
|
||||
/// </summary>
|
||||
event Action<IKeyboard, Key, int> KeyDown;
|
||||
event Action<IKeyboard, Key, int>? KeyDown;
|
||||
|
||||
/// <summary>
|
||||
/// Called when a key is released.
|
||||
/// </summary>
|
||||
event Action<IKeyboard, Key, int> KeyUp;
|
||||
event Action<IKeyboard, Key, int>? KeyUp;
|
||||
|
||||
/// <summary>
|
||||
/// Called when a character is received.
|
||||
/// </summary>
|
||||
event Action<IKeyboard, char> KeyChar;
|
||||
event Action<IKeyboard, char>? KeyChar;
|
||||
}
|
||||
}
|
|
@ -35,6 +35,7 @@ namespace Silk.NET.Input
|
|||
/// </summary>
|
||||
ICursor Cursor { get; }
|
||||
|
||||
/// <summary>
|
||||
/// The maximum time in milliseconds between two
|
||||
/// consecutive clicks to count as a double click.
|
||||
/// </summary>
|
||||
|
@ -66,12 +67,12 @@ namespace Silk.NET.Input
|
|||
/// <summary>
|
||||
/// Called when a single click is performed.
|
||||
/// </summary>
|
||||
event Action<IMouse, MouseButton> Click;
|
||||
event Action<IMouse, MouseButton, PointF> Click;
|
||||
|
||||
/// <summary>
|
||||
/// Called when a double click is performed.
|
||||
/// </summary>
|
||||
event Action<IMouse, MouseButton> DoubleClick;
|
||||
event Action<IMouse, MouseButton, PointF> DoubleClick;
|
||||
|
||||
/// <summary>
|
||||
/// Called when the mouse is moved.
|
||||
|
|
|
@ -3,6 +3,7 @@
|
|||
<PropertyGroup>
|
||||
<TargetFramework>netstandard2.0</TargetFramework>
|
||||
<RootNamespace>Silk.NET.Input</RootNamespace>
|
||||
<Nullable>enable</Nullable>
|
||||
</PropertyGroup>
|
||||
|
||||
<ItemGroup>
|
||||
|
|
|
@ -1,3 +1,4 @@
|
|||
<wpf:ResourceDictionary xml:space="preserve" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" xmlns:s="clr-namespace:System;assembly=mscorlib" xmlns:ss="urn:shemas-jetbrains-com:settings-storage-xaml" xmlns:wpf="http://schemas.microsoft.com/winfx/2006/xaml/presentation">
|
||||
<s:Boolean x:Key="/Default/CodeInspection/NamespaceProvider/NamespaceFoldersToSkip/=enums/@EntryIndexedValue">True</s:Boolean>
|
||||
<s:Boolean x:Key="/Default/CodeInspection/NamespaceProvider/NamespaceFoldersToSkip/=interfaces/@EntryIndexedValue">True</s:Boolean></wpf:ResourceDictionary>
|
||||
<s:Boolean x:Key="/Default/CodeInspection/NamespaceProvider/NamespaceFoldersToSkip/=interfaces/@EntryIndexedValue">True</s:Boolean>
|
||||
<s:Boolean x:Key="/Default/CodeInspection/NamespaceProvider/NamespaceFoldersToSkip/=structs/@EntryIndexedValue">True</s:Boolean></wpf:ResourceDictionary>
|
|
@ -5,6 +5,7 @@
|
|||
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using Silk.NET.Core;
|
||||
using Silk.NET.GLFW;
|
||||
|
||||
namespace Silk.NET.Input.Glfw
|
||||
|
@ -14,7 +15,7 @@ namespace Silk.NET.Input.Glfw
|
|||
/// </summary>
|
||||
internal class GlfwCursor : ICursor, IDisposable
|
||||
{
|
||||
private static readonly Dictionary<StandardCursor, CursorShape> CursorShapes = new Dictionary<StandardCursor, CursorShape>
|
||||
private static readonly Dictionary<StandardCursor, CursorShape> _cursorShapes = new Dictionary<StandardCursor, CursorShape>
|
||||
{
|
||||
{ StandardCursor.Arrow, CursorShape.Arrow },
|
||||
{ StandardCursor.IBeam, CursorShape.IBeam },
|
||||
|
@ -31,9 +32,7 @@ namespace Silk.NET.Input.Glfw
|
|||
private StandardCursor _standardCursor = StandardCursor.Default;
|
||||
private int _hotspotX = 0;
|
||||
private int _hotspotY = 0;
|
||||
private int _width = 0;
|
||||
private int _height = 0;
|
||||
private byte[] _pixels = null;
|
||||
private RawImage _image;
|
||||
|
||||
internal unsafe GlfwCursor(WindowHandle* handle)
|
||||
{
|
||||
|
@ -126,42 +125,14 @@ namespace Silk.NET.Input.Glfw
|
|||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
public int Width
|
||||
public RawImage Image
|
||||
{
|
||||
get => _width;
|
||||
get => _image;
|
||||
set
|
||||
{
|
||||
if (_width != value)
|
||||
if (_image != value)
|
||||
{
|
||||
_width = value;
|
||||
UpdateCustomCursor();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
public int Height
|
||||
{
|
||||
get => _height;
|
||||
set
|
||||
{
|
||||
if (_height != value)
|
||||
{
|
||||
_height = value;
|
||||
UpdateCustomCursor();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
public byte[] Pixels
|
||||
{
|
||||
get => _pixels;
|
||||
set
|
||||
{
|
||||
if (_pixels != value)
|
||||
{
|
||||
_pixels = value;
|
||||
_image = value;
|
||||
UpdateCustomCursor();
|
||||
}
|
||||
}
|
||||
|
@ -231,32 +202,32 @@ namespace Silk.NET.Input.Glfw
|
|||
return null;
|
||||
else
|
||||
{
|
||||
if (!CursorShapes.ContainsKey(_standardCursor))
|
||||
if (!_cursorShapes.ContainsKey(_standardCursor))
|
||||
throw new InvalidOperationException("Glfw does not support the given standard cursor.");
|
||||
|
||||
return GlfwProvider.GLFW.Value.CreateStandardCursor(CursorShapes[_standardCursor]);
|
||||
return GlfwProvider.GLFW.Value.CreateStandardCursor(_cursorShapes[_standardCursor]);
|
||||
}
|
||||
}
|
||||
|
||||
private unsafe Cursor* CreateCustomCursor()
|
||||
{
|
||||
if (Pixels == null || Pixels.Length == 0 || Width <= 0 || Height <= 0)
|
||||
if (_image.Pixels.IsEmpty || _image.Width <= 0 || _image.Height <= 0)
|
||||
return null;
|
||||
|
||||
if (Pixels.Length % BytesPerCursorPixel != 0)
|
||||
if (_image.Pixels.Length % BytesPerCursorPixel != 0)
|
||||
throw new ArgumentOutOfRangeException($"Pixel data must provide a multiple of {BytesPerCursorPixel} bytes.");
|
||||
|
||||
// the user might setup the values step-by-step, so use the
|
||||
// default cursor as long as the custom cursor state is not valid
|
||||
if (Width * Height * BytesPerCursorPixel != Pixels.Length)
|
||||
if (_image.Width * _image.Height * BytesPerCursorPixel != _image.Pixels.Length)
|
||||
return null;
|
||||
|
||||
fixed (byte* ptr = Pixels)
|
||||
fixed (byte* ptr = _image.Pixels.Span)
|
||||
{
|
||||
var image = new Image
|
||||
{
|
||||
Width = Width,
|
||||
Height = Height,
|
||||
Width = _image.Width,
|
||||
Height = _image.Height,
|
||||
Pixels = ptr
|
||||
};
|
||||
|
||||
|
|
|
@ -98,6 +98,6 @@ namespace Silk.NET.Input.Glfw
|
|||
public IReadOnlyList<IKeyboard> Keyboards { get; }
|
||||
public IReadOnlyList<IMouse> Mice { get; }
|
||||
public IReadOnlyList<IInputDevice> OtherDevices { get; } = new IInputDevice[0];
|
||||
public event Action<IInputDevice, bool> ConnectionChanged;
|
||||
public event Action<IInputDevice, bool>? ConnectionChanged;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -18,8 +18,7 @@ namespace Silk.NET.Input.Glfw
|
|||
/// <inheritdoc />
|
||||
internal class GlfwInputPlatform : IInputPlatform
|
||||
{
|
||||
public GlfwInputPlatform(){}
|
||||
private static Dictionary<IntPtr, GlfwEvents> _subs = new Dictionary<IntPtr, GlfwEvents>();
|
||||
private static readonly Dictionary<IntPtr, GlfwEvents> _subs = new Dictionary<IntPtr, GlfwEvents>();
|
||||
/// <inheritdoc />
|
||||
public bool IsApplicable(IView window) => window is GlfwWindow;
|
||||
|
||||
|
|
|
@ -13,7 +13,7 @@ namespace Silk.NET.Input.Glfw
|
|||
{
|
||||
private bool _connected;
|
||||
|
||||
public unsafe GlfwJoystick(int i)
|
||||
public GlfwJoystick(int i)
|
||||
{
|
||||
Index = i;
|
||||
Axes = new Axis[0];
|
||||
|
@ -32,10 +32,10 @@ namespace Silk.NET.Input.Glfw
|
|||
public IReadOnlyList<Button> Buttons { get; private set; }
|
||||
public IReadOnlyList<Hat> Hats { get; private set; }
|
||||
public Deadzone Deadzone { get; set; }
|
||||
public event Action<IJoystick, Button> ButtonDown;
|
||||
public event Action<IJoystick, Button> ButtonUp;
|
||||
public event Action<IJoystick, Axis> AxisMoved;
|
||||
public event Action<IJoystick, Hat> HatMoved;
|
||||
public event Action<IJoystick, Button>? ButtonDown;
|
||||
public event Action<IJoystick, Button>? ButtonUp;
|
||||
public event Action<IJoystick, Axis>? AxisMoved;
|
||||
public event Action<IJoystick, Hat>? HatMoved;
|
||||
public unsafe void Update()
|
||||
{
|
||||
if (!IsConnected)
|
||||
|
@ -91,7 +91,7 @@ namespace Silk.NET.Input.Glfw
|
|||
}
|
||||
}
|
||||
|
||||
public unsafe void EnsureAxesSize(int count)
|
||||
public void EnsureAxesSize(int count)
|
||||
{
|
||||
if (Axes.Count == count)
|
||||
{
|
||||
|
@ -103,7 +103,7 @@ namespace Silk.NET.Input.Glfw
|
|||
Axes = axes;
|
||||
}
|
||||
|
||||
public unsafe void EnsureButtonSize(int count)
|
||||
public void EnsureButtonSize(int count)
|
||||
{
|
||||
if (Buttons.Count == count)
|
||||
{
|
||||
|
@ -115,7 +115,7 @@ namespace Silk.NET.Input.Glfw
|
|||
Buttons = buttons;
|
||||
}
|
||||
|
||||
public unsafe void EnsureHatSize(int count)
|
||||
public void EnsureHatSize(int count)
|
||||
{
|
||||
if (Hats.Count == count)
|
||||
{
|
||||
|
@ -131,6 +131,6 @@ namespace Silk.NET.Input.Glfw
|
|||
{
|
||||
}
|
||||
|
||||
public Action<IInputDevice, bool> OnConnectionChanged { get; set; }
|
||||
public Action<IInputDevice, bool>? OnConnectionChanged { get; set; }
|
||||
}
|
||||
}
|
||||
|
|
|
@ -12,21 +12,21 @@ namespace Silk.NET.Input.Glfw
|
|||
{
|
||||
internal class GlfwKeyboard : IKeyboard, IGlfwSubscriber
|
||||
{
|
||||
private static readonly Key[] Keys = ((Keys[]) Enum.GetValues(typeof(Keys))).Select(ConvertKey).ToArray();
|
||||
private static readonly Key[] _keys = ((Keys[]) Enum.GetValues(typeof(Keys))).Select(ConvertKey).ToArray();
|
||||
private unsafe WindowHandle* _handle;
|
||||
private GlfwCallbacks.CharCallback _char;
|
||||
private GlfwCallbacks.KeyCallback _key;
|
||||
private GlfwCallbacks.CharCallback? _char;
|
||||
private GlfwCallbacks.KeyCallback? _key;
|
||||
public string Name { get; } = "Silk.NET Keyboard (via GLFW)";
|
||||
public int Index { get; } = 0;
|
||||
public bool IsConnected { get; } = true;
|
||||
public IReadOnlyList<Key> SupportedKeys { get; } = Keys;
|
||||
public IReadOnlyList<Key> SupportedKeys { get; } = _keys;
|
||||
|
||||
public unsafe bool IsKeyPressed
|
||||
(Key key) => GlfwProvider.GLFW.Value.GetKey(_handle, ConvertKey(key)) == (int) InputAction.Press;
|
||||
|
||||
public event Action<IKeyboard, Key, int> KeyDown;
|
||||
public event Action<IKeyboard, Key, int> KeyUp;
|
||||
public event Action<IKeyboard, char> KeyChar;
|
||||
public event Action<IKeyboard, Key, int>? KeyDown;
|
||||
public event Action<IKeyboard, Key, int>? KeyUp;
|
||||
public event Action<IKeyboard, char>? KeyChar;
|
||||
|
||||
|
||||
public unsafe void Subscribe(GlfwEvents events)
|
||||
|
@ -51,253 +51,253 @@ namespace Silk.NET.Input.Glfw
|
|||
|
||||
private static Key ConvertKey(Keys keys) => keys switch
|
||||
{
|
||||
GLFW.Keys.Unknown => Key.Unknown,
|
||||
GLFW.Keys.Space => Key.Space,
|
||||
GLFW.Keys.Apostrophe => Key.Apostrophe,
|
||||
GLFW.Keys.Comma => Key.Comma,
|
||||
GLFW.Keys.Minus => Key.Minus,
|
||||
GLFW.Keys.Period => Key.Period,
|
||||
GLFW.Keys.Slash => Key.Slash,
|
||||
GLFW.Keys.Number0 => Key.Number0,
|
||||
GLFW.Keys.Number1 => Key.Number1,
|
||||
GLFW.Keys.Number2 => Key.Number2,
|
||||
GLFW.Keys.Number3 => Key.Number3,
|
||||
GLFW.Keys.Number4 => Key.Number4,
|
||||
GLFW.Keys.Number5 => Key.Number5,
|
||||
GLFW.Keys.Number6 => Key.Number6,
|
||||
GLFW.Keys.Number7 => Key.Number7,
|
||||
GLFW.Keys.Number8 => Key.Number8,
|
||||
GLFW.Keys.Number9 => Key.Number9,
|
||||
GLFW.Keys.Semicolon => Key.Semicolon,
|
||||
GLFW.Keys.Equal => Key.Equal,
|
||||
GLFW.Keys.A => Key.A,
|
||||
GLFW.Keys.B => Key.B,
|
||||
GLFW.Keys.C => Key.C,
|
||||
GLFW.Keys.D => Key.D,
|
||||
GLFW.Keys.E => Key.E,
|
||||
GLFW.Keys.F => Key.F,
|
||||
GLFW.Keys.G => Key.G,
|
||||
GLFW.Keys.H => Key.H,
|
||||
GLFW.Keys.I => Key.I,
|
||||
GLFW.Keys.J => Key.J,
|
||||
GLFW.Keys.K => Key.K,
|
||||
GLFW.Keys.L => Key.L,
|
||||
GLFW.Keys.M => Key.M,
|
||||
GLFW.Keys.N => Key.N,
|
||||
GLFW.Keys.O => Key.O,
|
||||
GLFW.Keys.P => Key.P,
|
||||
GLFW.Keys.Q => Key.Q,
|
||||
GLFW.Keys.R => Key.R,
|
||||
GLFW.Keys.S => Key.S,
|
||||
GLFW.Keys.T => Key.T,
|
||||
GLFW.Keys.U => Key.U,
|
||||
GLFW.Keys.V => Key.V,
|
||||
GLFW.Keys.W => Key.W,
|
||||
GLFW.Keys.X => Key.X,
|
||||
GLFW.Keys.Y => Key.Y,
|
||||
GLFW.Keys.Z => Key.Z,
|
||||
GLFW.Keys.LeftBracket => Key.LeftBracket,
|
||||
GLFW.Keys.BackSlash => Key.BackSlash,
|
||||
GLFW.Keys.RightBracket => Key.RightBracket,
|
||||
GLFW.Keys.GraveAccent => Key.GraveAccent,
|
||||
GLFW.Keys.World1 => Key.World1,
|
||||
GLFW.Keys.World2 => Key.World2,
|
||||
GLFW.Keys.Escape => Key.Escape,
|
||||
GLFW.Keys.Enter => Key.Enter,
|
||||
GLFW.Keys.Tab => Key.Tab,
|
||||
GLFW.Keys.Backspace => Key.Backspace,
|
||||
GLFW.Keys.Insert => Key.Insert,
|
||||
GLFW.Keys.Delete => Key.Delete,
|
||||
GLFW.Keys.Right => Key.Right,
|
||||
GLFW.Keys.Left => Key.Left,
|
||||
GLFW.Keys.Down => Key.Down,
|
||||
GLFW.Keys.Up => Key.Up,
|
||||
GLFW.Keys.PageUp => Key.PageUp,
|
||||
GLFW.Keys.PageDown => Key.PageDown,
|
||||
GLFW.Keys.Home => Key.Home,
|
||||
GLFW.Keys.End => Key.End,
|
||||
GLFW.Keys.CapsLock => Key.CapsLock,
|
||||
GLFW.Keys.ScrollLock => Key.ScrollLock,
|
||||
GLFW.Keys.NumLock => Key.NumLock,
|
||||
GLFW.Keys.PrintScreen => Key.PrintScreen,
|
||||
GLFW.Keys.Pause => Key.Pause,
|
||||
GLFW.Keys.F1 => Key.F1,
|
||||
GLFW.Keys.F2 => Key.F2,
|
||||
GLFW.Keys.F3 => Key.F3,
|
||||
GLFW.Keys.F4 => Key.F4,
|
||||
GLFW.Keys.F5 => Key.F5,
|
||||
GLFW.Keys.F6 => Key.F6,
|
||||
GLFW.Keys.F7 => Key.F7,
|
||||
GLFW.Keys.F8 => Key.F8,
|
||||
GLFW.Keys.F9 => Key.F9,
|
||||
GLFW.Keys.F10 => Key.F10,
|
||||
GLFW.Keys.F11 => Key.F11,
|
||||
GLFW.Keys.F12 => Key.F12,
|
||||
GLFW.Keys.F13 => Key.F13,
|
||||
GLFW.Keys.F14 => Key.F14,
|
||||
GLFW.Keys.F15 => Key.F15,
|
||||
GLFW.Keys.F16 => Key.F16,
|
||||
GLFW.Keys.F17 => Key.F17,
|
||||
GLFW.Keys.F18 => Key.F18,
|
||||
GLFW.Keys.F19 => Key.F19,
|
||||
GLFW.Keys.F20 => Key.F20,
|
||||
GLFW.Keys.F21 => Key.F21,
|
||||
GLFW.Keys.F22 => Key.F22,
|
||||
GLFW.Keys.F23 => Key.F23,
|
||||
GLFW.Keys.F24 => Key.F24,
|
||||
GLFW.Keys.F25 => Key.F25,
|
||||
GLFW.Keys.Keypad0 => Key.Keypad0,
|
||||
GLFW.Keys.Keypad1 => Key.Keypad1,
|
||||
GLFW.Keys.Keypad2 => Key.Keypad2,
|
||||
GLFW.Keys.Keypad3 => Key.Keypad3,
|
||||
GLFW.Keys.Keypad4 => Key.Keypad4,
|
||||
GLFW.Keys.Keypad5 => Key.Keypad5,
|
||||
GLFW.Keys.Keypad6 => Key.Keypad6,
|
||||
GLFW.Keys.Keypad7 => Key.Keypad7,
|
||||
GLFW.Keys.Keypad8 => Key.Keypad8,
|
||||
GLFW.Keys.Keypad9 => Key.Keypad9,
|
||||
GLFW.Keys.KeypadDecimal => Key.KeypadDecimal,
|
||||
GLFW.Keys.KeypadDivide => Key.KeypadDivide,
|
||||
GLFW.Keys.KeypadMultiply => Key.KeypadMultiply,
|
||||
GLFW.Keys.KeypadSubtract => Key.KeypadSubtract,
|
||||
GLFW.Keys.KeypadAdd => Key.KeypadAdd,
|
||||
GLFW.Keys.KeypadEnter => Key.KeypadEnter,
|
||||
GLFW.Keys.KeypadEqual => Key.KeypadEqual,
|
||||
GLFW.Keys.ShiftLeft => Key.ShiftLeft,
|
||||
GLFW.Keys.ControlLeft => Key.ControlLeft,
|
||||
GLFW.Keys.AltLeft => Key.AltLeft,
|
||||
GLFW.Keys.SuperLeft => Key.SuperLeft,
|
||||
GLFW.Keys.ShiftRight => Key.ShiftRight,
|
||||
GLFW.Keys.ControlRight => Key.ControlRight,
|
||||
GLFW.Keys.AltRight => Key.AltRight,
|
||||
GLFW.Keys.SuperRight => Key.SuperRight,
|
||||
GLFW.Keys.Menu => Key.Menu,
|
||||
Keys.Unknown => Key.Unknown,
|
||||
Keys.Space => Key.Space,
|
||||
Keys.Apostrophe => Key.Apostrophe,
|
||||
Keys.Comma => Key.Comma,
|
||||
Keys.Minus => Key.Minus,
|
||||
Keys.Period => Key.Period,
|
||||
Keys.Slash => Key.Slash,
|
||||
Keys.Number0 => Key.Number0,
|
||||
Keys.Number1 => Key.Number1,
|
||||
Keys.Number2 => Key.Number2,
|
||||
Keys.Number3 => Key.Number3,
|
||||
Keys.Number4 => Key.Number4,
|
||||
Keys.Number5 => Key.Number5,
|
||||
Keys.Number6 => Key.Number6,
|
||||
Keys.Number7 => Key.Number7,
|
||||
Keys.Number8 => Key.Number8,
|
||||
Keys.Number9 => Key.Number9,
|
||||
Keys.Semicolon => Key.Semicolon,
|
||||
Keys.Equal => Key.Equal,
|
||||
Keys.A => Key.A,
|
||||
Keys.B => Key.B,
|
||||
Keys.C => Key.C,
|
||||
Keys.D => Key.D,
|
||||
Keys.E => Key.E,
|
||||
Keys.F => Key.F,
|
||||
Keys.G => Key.G,
|
||||
Keys.H => Key.H,
|
||||
Keys.I => Key.I,
|
||||
Keys.J => Key.J,
|
||||
Keys.K => Key.K,
|
||||
Keys.L => Key.L,
|
||||
Keys.M => Key.M,
|
||||
Keys.N => Key.N,
|
||||
Keys.O => Key.O,
|
||||
Keys.P => Key.P,
|
||||
Keys.Q => Key.Q,
|
||||
Keys.R => Key.R,
|
||||
Keys.S => Key.S,
|
||||
Keys.T => Key.T,
|
||||
Keys.U => Key.U,
|
||||
Keys.V => Key.V,
|
||||
Keys.W => Key.W,
|
||||
Keys.X => Key.X,
|
||||
Keys.Y => Key.Y,
|
||||
Keys.Z => Key.Z,
|
||||
Keys.LeftBracket => Key.LeftBracket,
|
||||
Keys.BackSlash => Key.BackSlash,
|
||||
Keys.RightBracket => Key.RightBracket,
|
||||
Keys.GraveAccent => Key.GraveAccent,
|
||||
Keys.World1 => Key.World1,
|
||||
Keys.World2 => Key.World2,
|
||||
Keys.Escape => Key.Escape,
|
||||
Keys.Enter => Key.Enter,
|
||||
Keys.Tab => Key.Tab,
|
||||
Keys.Backspace => Key.Backspace,
|
||||
Keys.Insert => Key.Insert,
|
||||
Keys.Delete => Key.Delete,
|
||||
Keys.Right => Key.Right,
|
||||
Keys.Left => Key.Left,
|
||||
Keys.Down => Key.Down,
|
||||
Keys.Up => Key.Up,
|
||||
Keys.PageUp => Key.PageUp,
|
||||
Keys.PageDown => Key.PageDown,
|
||||
Keys.Home => Key.Home,
|
||||
Keys.End => Key.End,
|
||||
Keys.CapsLock => Key.CapsLock,
|
||||
Keys.ScrollLock => Key.ScrollLock,
|
||||
Keys.NumLock => Key.NumLock,
|
||||
Keys.PrintScreen => Key.PrintScreen,
|
||||
Keys.Pause => Key.Pause,
|
||||
Keys.F1 => Key.F1,
|
||||
Keys.F2 => Key.F2,
|
||||
Keys.F3 => Key.F3,
|
||||
Keys.F4 => Key.F4,
|
||||
Keys.F5 => Key.F5,
|
||||
Keys.F6 => Key.F6,
|
||||
Keys.F7 => Key.F7,
|
||||
Keys.F8 => Key.F8,
|
||||
Keys.F9 => Key.F9,
|
||||
Keys.F10 => Key.F10,
|
||||
Keys.F11 => Key.F11,
|
||||
Keys.F12 => Key.F12,
|
||||
Keys.F13 => Key.F13,
|
||||
Keys.F14 => Key.F14,
|
||||
Keys.F15 => Key.F15,
|
||||
Keys.F16 => Key.F16,
|
||||
Keys.F17 => Key.F17,
|
||||
Keys.F18 => Key.F18,
|
||||
Keys.F19 => Key.F19,
|
||||
Keys.F20 => Key.F20,
|
||||
Keys.F21 => Key.F21,
|
||||
Keys.F22 => Key.F22,
|
||||
Keys.F23 => Key.F23,
|
||||
Keys.F24 => Key.F24,
|
||||
Keys.F25 => Key.F25,
|
||||
Keys.Keypad0 => Key.Keypad0,
|
||||
Keys.Keypad1 => Key.Keypad1,
|
||||
Keys.Keypad2 => Key.Keypad2,
|
||||
Keys.Keypad3 => Key.Keypad3,
|
||||
Keys.Keypad4 => Key.Keypad4,
|
||||
Keys.Keypad5 => Key.Keypad5,
|
||||
Keys.Keypad6 => Key.Keypad6,
|
||||
Keys.Keypad7 => Key.Keypad7,
|
||||
Keys.Keypad8 => Key.Keypad8,
|
||||
Keys.Keypad9 => Key.Keypad9,
|
||||
Keys.KeypadDecimal => Key.KeypadDecimal,
|
||||
Keys.KeypadDivide => Key.KeypadDivide,
|
||||
Keys.KeypadMultiply => Key.KeypadMultiply,
|
||||
Keys.KeypadSubtract => Key.KeypadSubtract,
|
||||
Keys.KeypadAdd => Key.KeypadAdd,
|
||||
Keys.KeypadEnter => Key.KeypadEnter,
|
||||
Keys.KeypadEqual => Key.KeypadEqual,
|
||||
Keys.ShiftLeft => Key.ShiftLeft,
|
||||
Keys.ControlLeft => Key.ControlLeft,
|
||||
Keys.AltLeft => Key.AltLeft,
|
||||
Keys.SuperLeft => Key.SuperLeft,
|
||||
Keys.ShiftRight => Key.ShiftRight,
|
||||
Keys.ControlRight => Key.ControlRight,
|
||||
Keys.AltRight => Key.AltRight,
|
||||
Keys.SuperRight => Key.SuperRight,
|
||||
Keys.Menu => Key.Menu,
|
||||
_ => throw new ArgumentOutOfRangeException()
|
||||
};
|
||||
|
||||
private static Keys ConvertKey(Key keys) => keys switch
|
||||
{
|
||||
Key.Unknown => GLFW.Keys.Unknown,
|
||||
Key.Space => GLFW.Keys.Space,
|
||||
Key.Apostrophe => GLFW.Keys.Apostrophe,
|
||||
Key.Comma => GLFW.Keys.Comma,
|
||||
Key.Minus => GLFW.Keys.Minus,
|
||||
Key.Period => GLFW.Keys.Period,
|
||||
Key.Slash => GLFW.Keys.Slash,
|
||||
Key.Number0 => GLFW.Keys.Number0,
|
||||
Key.Number1 => GLFW.Keys.Number1,
|
||||
Key.Number2 => GLFW.Keys.Number2,
|
||||
Key.Number3 => GLFW.Keys.Number3,
|
||||
Key.Number4 => GLFW.Keys.Number4,
|
||||
Key.Number5 => GLFW.Keys.Number5,
|
||||
Key.Number6 => GLFW.Keys.Number6,
|
||||
Key.Number7 => GLFW.Keys.Number7,
|
||||
Key.Number8 => GLFW.Keys.Number8,
|
||||
Key.Number9 => GLFW.Keys.Number9,
|
||||
Key.Semicolon => GLFW.Keys.Semicolon,
|
||||
Key.Equal => GLFW.Keys.Equal,
|
||||
Key.A => GLFW.Keys.A,
|
||||
Key.B => GLFW.Keys.B,
|
||||
Key.C => GLFW.Keys.C,
|
||||
Key.D => GLFW.Keys.D,
|
||||
Key.E => GLFW.Keys.E,
|
||||
Key.F => GLFW.Keys.F,
|
||||
Key.G => GLFW.Keys.G,
|
||||
Key.H => GLFW.Keys.H,
|
||||
Key.I => GLFW.Keys.I,
|
||||
Key.J => GLFW.Keys.J,
|
||||
Key.K => GLFW.Keys.K,
|
||||
Key.L => GLFW.Keys.L,
|
||||
Key.M => GLFW.Keys.M,
|
||||
Key.N => GLFW.Keys.N,
|
||||
Key.O => GLFW.Keys.O,
|
||||
Key.P => GLFW.Keys.P,
|
||||
Key.Q => GLFW.Keys.Q,
|
||||
Key.R => GLFW.Keys.R,
|
||||
Key.S => GLFW.Keys.S,
|
||||
Key.T => GLFW.Keys.T,
|
||||
Key.U => GLFW.Keys.U,
|
||||
Key.V => GLFW.Keys.V,
|
||||
Key.W => GLFW.Keys.W,
|
||||
Key.X => GLFW.Keys.X,
|
||||
Key.Y => GLFW.Keys.Y,
|
||||
Key.Z => GLFW.Keys.Z,
|
||||
Key.LeftBracket => GLFW.Keys.LeftBracket,
|
||||
Key.BackSlash => GLFW.Keys.BackSlash,
|
||||
Key.RightBracket => GLFW.Keys.RightBracket,
|
||||
Key.GraveAccent => GLFW.Keys.GraveAccent,
|
||||
Key.World1 => GLFW.Keys.World1,
|
||||
Key.World2 => GLFW.Keys.World2,
|
||||
Key.Escape => GLFW.Keys.Escape,
|
||||
Key.Enter => GLFW.Keys.Enter,
|
||||
Key.Tab => GLFW.Keys.Tab,
|
||||
Key.Backspace => GLFW.Keys.Backspace,
|
||||
Key.Insert => GLFW.Keys.Insert,
|
||||
Key.Delete => GLFW.Keys.Delete,
|
||||
Key.Right => GLFW.Keys.Right,
|
||||
Key.Left => GLFW.Keys.Left,
|
||||
Key.Down => GLFW.Keys.Down,
|
||||
Key.Up => GLFW.Keys.Up,
|
||||
Key.PageUp => GLFW.Keys.PageUp,
|
||||
Key.PageDown => GLFW.Keys.PageDown,
|
||||
Key.Home => GLFW.Keys.Home,
|
||||
Key.End => GLFW.Keys.End,
|
||||
Key.CapsLock => GLFW.Keys.CapsLock,
|
||||
Key.ScrollLock => GLFW.Keys.ScrollLock,
|
||||
Key.NumLock => GLFW.Keys.NumLock,
|
||||
Key.PrintScreen => GLFW.Keys.PrintScreen,
|
||||
Key.Pause => GLFW.Keys.Pause,
|
||||
Key.F1 => GLFW.Keys.F1,
|
||||
Key.F2 => GLFW.Keys.F2,
|
||||
Key.F3 => GLFW.Keys.F3,
|
||||
Key.F4 => GLFW.Keys.F4,
|
||||
Key.F5 => GLFW.Keys.F5,
|
||||
Key.F6 => GLFW.Keys.F6,
|
||||
Key.F7 => GLFW.Keys.F7,
|
||||
Key.F8 => GLFW.Keys.F8,
|
||||
Key.F9 => GLFW.Keys.F9,
|
||||
Key.F10 => GLFW.Keys.F10,
|
||||
Key.F11 => GLFW.Keys.F11,
|
||||
Key.F12 => GLFW.Keys.F12,
|
||||
Key.F13 => GLFW.Keys.F13,
|
||||
Key.F14 => GLFW.Keys.F14,
|
||||
Key.F15 => GLFW.Keys.F15,
|
||||
Key.F16 => GLFW.Keys.F16,
|
||||
Key.F17 => GLFW.Keys.F17,
|
||||
Key.F18 => GLFW.Keys.F18,
|
||||
Key.F19 => GLFW.Keys.F19,
|
||||
Key.F20 => GLFW.Keys.F20,
|
||||
Key.F21 => GLFW.Keys.F21,
|
||||
Key.F22 => GLFW.Keys.F22,
|
||||
Key.F23 => GLFW.Keys.F23,
|
||||
Key.F24 => GLFW.Keys.F24,
|
||||
Key.F25 => GLFW.Keys.F25,
|
||||
Key.Keypad0 => GLFW.Keys.Keypad0,
|
||||
Key.Keypad1 => GLFW.Keys.Keypad1,
|
||||
Key.Keypad2 => GLFW.Keys.Keypad2,
|
||||
Key.Keypad3 => GLFW.Keys.Keypad3,
|
||||
Key.Keypad4 => GLFW.Keys.Keypad4,
|
||||
Key.Keypad5 => GLFW.Keys.Keypad5,
|
||||
Key.Keypad6 => GLFW.Keys.Keypad6,
|
||||
Key.Keypad7 => GLFW.Keys.Keypad7,
|
||||
Key.Keypad8 => GLFW.Keys.Keypad8,
|
||||
Key.Keypad9 => GLFW.Keys.Keypad9,
|
||||
Key.KeypadDecimal => GLFW.Keys.KeypadDecimal,
|
||||
Key.KeypadDivide => GLFW.Keys.KeypadDivide,
|
||||
Key.KeypadMultiply => GLFW.Keys.KeypadMultiply,
|
||||
Key.KeypadSubtract => GLFW.Keys.KeypadSubtract,
|
||||
Key.KeypadAdd => GLFW.Keys.KeypadAdd,
|
||||
Key.KeypadEnter => GLFW.Keys.KeypadEnter,
|
||||
Key.KeypadEqual => GLFW.Keys.KeypadEqual,
|
||||
Key.ShiftLeft => GLFW.Keys.ShiftLeft,
|
||||
Key.ControlLeft => GLFW.Keys.ControlLeft,
|
||||
Key.AltLeft => GLFW.Keys.AltLeft,
|
||||
Key.SuperLeft => GLFW.Keys.SuperLeft,
|
||||
Key.ShiftRight => GLFW.Keys.ShiftRight,
|
||||
Key.ControlRight => GLFW.Keys.ControlRight,
|
||||
Key.AltRight => GLFW.Keys.AltRight,
|
||||
Key.SuperRight => GLFW.Keys.SuperRight,
|
||||
Key.Menu => GLFW.Keys.Menu,
|
||||
Key.Unknown => Keys.Unknown,
|
||||
Key.Space => Keys.Space,
|
||||
Key.Apostrophe => Keys.Apostrophe,
|
||||
Key.Comma => Keys.Comma,
|
||||
Key.Minus => Keys.Minus,
|
||||
Key.Period => Keys.Period,
|
||||
Key.Slash => Keys.Slash,
|
||||
Key.Number0 => Keys.Number0,
|
||||
Key.Number1 => Keys.Number1,
|
||||
Key.Number2 => Keys.Number2,
|
||||
Key.Number3 => Keys.Number3,
|
||||
Key.Number4 => Keys.Number4,
|
||||
Key.Number5 => Keys.Number5,
|
||||
Key.Number6 => Keys.Number6,
|
||||
Key.Number7 => Keys.Number7,
|
||||
Key.Number8 => Keys.Number8,
|
||||
Key.Number9 => Keys.Number9,
|
||||
Key.Semicolon => Keys.Semicolon,
|
||||
Key.Equal => Keys.Equal,
|
||||
Key.A => Keys.A,
|
||||
Key.B => Keys.B,
|
||||
Key.C => Keys.C,
|
||||
Key.D => Keys.D,
|
||||
Key.E => Keys.E,
|
||||
Key.F => Keys.F,
|
||||
Key.G => Keys.G,
|
||||
Key.H => Keys.H,
|
||||
Key.I => Keys.I,
|
||||
Key.J => Keys.J,
|
||||
Key.K => Keys.K,
|
||||
Key.L => Keys.L,
|
||||
Key.M => Keys.M,
|
||||
Key.N => Keys.N,
|
||||
Key.O => Keys.O,
|
||||
Key.P => Keys.P,
|
||||
Key.Q => Keys.Q,
|
||||
Key.R => Keys.R,
|
||||
Key.S => Keys.S,
|
||||
Key.T => Keys.T,
|
||||
Key.U => Keys.U,
|
||||
Key.V => Keys.V,
|
||||
Key.W => Keys.W,
|
||||
Key.X => Keys.X,
|
||||
Key.Y => Keys.Y,
|
||||
Key.Z => Keys.Z,
|
||||
Key.LeftBracket => Keys.LeftBracket,
|
||||
Key.BackSlash => Keys.BackSlash,
|
||||
Key.RightBracket => Keys.RightBracket,
|
||||
Key.GraveAccent => Keys.GraveAccent,
|
||||
Key.World1 => Keys.World1,
|
||||
Key.World2 => Keys.World2,
|
||||
Key.Escape => Keys.Escape,
|
||||
Key.Enter => Keys.Enter,
|
||||
Key.Tab => Keys.Tab,
|
||||
Key.Backspace => Keys.Backspace,
|
||||
Key.Insert => Keys.Insert,
|
||||
Key.Delete => Keys.Delete,
|
||||
Key.Right => Keys.Right,
|
||||
Key.Left => Keys.Left,
|
||||
Key.Down => Keys.Down,
|
||||
Key.Up => Keys.Up,
|
||||
Key.PageUp => Keys.PageUp,
|
||||
Key.PageDown => Keys.PageDown,
|
||||
Key.Home => Keys.Home,
|
||||
Key.End => Keys.End,
|
||||
Key.CapsLock => Keys.CapsLock,
|
||||
Key.ScrollLock => Keys.ScrollLock,
|
||||
Key.NumLock => Keys.NumLock,
|
||||
Key.PrintScreen => Keys.PrintScreen,
|
||||
Key.Pause => Keys.Pause,
|
||||
Key.F1 => Keys.F1,
|
||||
Key.F2 => Keys.F2,
|
||||
Key.F3 => Keys.F3,
|
||||
Key.F4 => Keys.F4,
|
||||
Key.F5 => Keys.F5,
|
||||
Key.F6 => Keys.F6,
|
||||
Key.F7 => Keys.F7,
|
||||
Key.F8 => Keys.F8,
|
||||
Key.F9 => Keys.F9,
|
||||
Key.F10 => Keys.F10,
|
||||
Key.F11 => Keys.F11,
|
||||
Key.F12 => Keys.F12,
|
||||
Key.F13 => Keys.F13,
|
||||
Key.F14 => Keys.F14,
|
||||
Key.F15 => Keys.F15,
|
||||
Key.F16 => Keys.F16,
|
||||
Key.F17 => Keys.F17,
|
||||
Key.F18 => Keys.F18,
|
||||
Key.F19 => Keys.F19,
|
||||
Key.F20 => Keys.F20,
|
||||
Key.F21 => Keys.F21,
|
||||
Key.F22 => Keys.F22,
|
||||
Key.F23 => Keys.F23,
|
||||
Key.F24 => Keys.F24,
|
||||
Key.F25 => Keys.F25,
|
||||
Key.Keypad0 => Keys.Keypad0,
|
||||
Key.Keypad1 => Keys.Keypad1,
|
||||
Key.Keypad2 => Keys.Keypad2,
|
||||
Key.Keypad3 => Keys.Keypad3,
|
||||
Key.Keypad4 => Keys.Keypad4,
|
||||
Key.Keypad5 => Keys.Keypad5,
|
||||
Key.Keypad6 => Keys.Keypad6,
|
||||
Key.Keypad7 => Keys.Keypad7,
|
||||
Key.Keypad8 => Keys.Keypad8,
|
||||
Key.Keypad9 => Keys.Keypad9,
|
||||
Key.KeypadDecimal => Keys.KeypadDecimal,
|
||||
Key.KeypadDivide => Keys.KeypadDivide,
|
||||
Key.KeypadMultiply => Keys.KeypadMultiply,
|
||||
Key.KeypadSubtract => Keys.KeypadSubtract,
|
||||
Key.KeypadAdd => Keys.KeypadAdd,
|
||||
Key.KeypadEnter => Keys.KeypadEnter,
|
||||
Key.KeypadEqual => Keys.KeypadEqual,
|
||||
Key.ShiftLeft => Keys.ShiftLeft,
|
||||
Key.ControlLeft => Keys.ControlLeft,
|
||||
Key.AltLeft => Keys.AltLeft,
|
||||
Key.SuperLeft => Keys.SuperLeft,
|
||||
Key.ShiftRight => Keys.ShiftRight,
|
||||
Key.ControlRight => Keys.ControlRight,
|
||||
Key.AltRight => Keys.AltRight,
|
||||
Key.SuperRight => Keys.SuperRight,
|
||||
Key.Menu => Keys.Menu,
|
||||
_ => throw new ArgumentOutOfRangeException()
|
||||
};
|
||||
|
||||
|
|
|
@ -15,14 +15,14 @@ namespace Silk.NET.Input.Glfw
|
|||
{
|
||||
internal class GlfwMouse : IMouse, IGlfwSubscriber, IDisposable
|
||||
{
|
||||
private static readonly MouseButton[] Buttons = ((MouseButton[]) Enum.GetValues(typeof(MouseButton)))
|
||||
private static readonly MouseButton[] _buttons = ((MouseButton[]) Enum.GetValues(typeof(MouseButton)))
|
||||
.Where(x => x != (MouseButton) (-1))
|
||||
.ToArray();
|
||||
|
||||
private unsafe WindowHandle* _handle;
|
||||
private GlfwCallbacks.ScrollCallback _scroll;
|
||||
private GlfwCallbacks.CursorPosCallback _cursorPos;
|
||||
private GlfwCallbacks.MouseButtonCallback _mouseButton;
|
||||
private GlfwCallbacks.ScrollCallback? _scroll;
|
||||
private GlfwCallbacks.CursorPosCallback? _cursorPos;
|
||||
private GlfwCallbacks.MouseButtonCallback? _mouseButton;
|
||||
private bool _firstClick = true;
|
||||
private bool _scrollModified = false;
|
||||
private MouseButton? _firstClickButton = null;
|
||||
|
@ -36,7 +36,7 @@ namespace Silk.NET.Input.Glfw
|
|||
public string Name { get; } = "Silk.NET Mouse (via GLFW)";
|
||||
public int Index { get; } = 0;
|
||||
public bool IsConnected { get; } = true;
|
||||
public IReadOnlyList<MouseButton> SupportedButtons { get; } = Buttons;
|
||||
public IReadOnlyList<MouseButton> SupportedButtons { get; } = _buttons;
|
||||
public IReadOnlyList<ScrollWheel> ScrollWheels { get; }
|
||||
|
||||
public unsafe PointF Position
|
||||
|
@ -67,8 +67,8 @@ namespace Silk.NET.Input.Glfw
|
|||
|
||||
public event Action<IMouse, MouseButton> MouseDown;
|
||||
public event Action<IMouse, MouseButton> MouseUp;
|
||||
public event Action<IMouse, MouseButton> Click;
|
||||
public event Action<IMouse, MouseButton> DoubleClick;
|
||||
public event Action<IMouse, MouseButton, PointF> Click;
|
||||
public event Action<IMouse, MouseButton, PointF> DoubleClick;
|
||||
public event Action<IMouse, PointF> MouseMove;
|
||||
public event Action<IMouse, ScrollWheel> Scroll;
|
||||
|
||||
|
@ -119,10 +119,10 @@ namespace Silk.NET.Input.Glfw
|
|||
// This is the first click with the given mouse button.
|
||||
_firstClickTime = null;
|
||||
|
||||
if (!_firstClick)
|
||||
if (!_firstClick && !(_firstClickButton is null))
|
||||
{
|
||||
// Only the mouse buttons differ so treat last click as a single click.
|
||||
Click?.Invoke(mouse, _firstClickButton.Value);
|
||||
Click?.Invoke(mouse, _firstClickButton.Value, Position);
|
||||
}
|
||||
|
||||
ProcessFirstClick(button);
|
||||
|
@ -142,13 +142,13 @@ namespace Silk.NET.Input.Glfw
|
|||
{
|
||||
// Second click was in time and in range -> double click.
|
||||
_firstClick = true;
|
||||
DoubleClick?.Invoke(mouse, button);
|
||||
DoubleClick?.Invoke(mouse, button, position);
|
||||
}
|
||||
else
|
||||
{
|
||||
// Second click was in time but outside range -> single click.
|
||||
// The second click is another "first click".
|
||||
Click?.Invoke(mouse, button);
|
||||
Click?.Invoke(mouse, button, position);
|
||||
ProcessFirstClick(button);
|
||||
}
|
||||
}
|
||||
|
@ -180,10 +180,13 @@ namespace Silk.NET.Input.Glfw
|
|||
{
|
||||
_firstClickTime = null;
|
||||
_firstClick = true;
|
||||
Click?.Invoke(this, _firstClickButton.Value);
|
||||
if (!(_firstClickButton is null))
|
||||
{
|
||||
Click?.Invoke(this, _firstClickButton.Value, Position);
|
||||
}
|
||||
}
|
||||
|
||||
public unsafe void Update()
|
||||
public void Update()
|
||||
{
|
||||
if (!_scrollModified)
|
||||
{
|
||||
|
|
|
@ -1,40 +0,0 @@
|
|||
// This file is part of Silk.NET.
|
||||
//
|
||||
// You may modify and distribute Silk.NET under the terms
|
||||
// of the MIT license. See the LICENSE file for details.
|
||||
|
||||
using System;
|
||||
using System.Collections;
|
||||
using System.Collections.Generic;
|
||||
|
||||
namespace Silk.NET.Input.Glfw
|
||||
{
|
||||
internal unsafe struct GlfwReadOnlyList<T> : IReadOnlyList<T>
|
||||
where T:unmanaged
|
||||
{
|
||||
private T* _items;
|
||||
|
||||
public GlfwReadOnlyList(T* items, int count)
|
||||
{
|
||||
Count = count;
|
||||
_items = items;
|
||||
}
|
||||
|
||||
public void Update(T* items, int count)
|
||||
{
|
||||
Count = count;
|
||||
_items = items;
|
||||
}
|
||||
|
||||
public IEnumerator<T> GetEnumerator() => new ReadOnlyListEnumerator<T>(this);
|
||||
|
||||
IEnumerator IEnumerable.GetEnumerator()
|
||||
{
|
||||
return GetEnumerator();
|
||||
}
|
||||
|
||||
public int Count { get; private set; }
|
||||
|
||||
public T this[int index] => index >= Count ? throw new ArgumentOutOfRangeException() : _items[index];
|
||||
}
|
||||
}
|
|
@ -1,12 +0,0 @@
|
|||
// This file is part of Silk.NET.
|
||||
//
|
||||
// You may modify and distribute Silk.NET under the terms
|
||||
// of the MIT license. See the LICENSE file for details.
|
||||
|
||||
namespace Silk.NET.Input.Glfw
|
||||
{
|
||||
internal interface IGlfwDevice : IInputDevice
|
||||
{
|
||||
bool IsConnected { get; }
|
||||
}
|
||||
}
|
|
@ -17,17 +17,14 @@ namespace Silk.NET.Input.Glfw
|
|||
{
|
||||
_list = list;
|
||||
_i = 0;
|
||||
Current = default;
|
||||
}
|
||||
public bool MoveNext()
|
||||
{
|
||||
if (_i >= _list.Count)
|
||||
{
|
||||
Current = default;
|
||||
return false;
|
||||
}
|
||||
|
||||
Current = _list[_i];
|
||||
_i++;
|
||||
return true;
|
||||
}
|
||||
|
@ -35,12 +32,11 @@ namespace Silk.NET.Input.Glfw
|
|||
public void Reset()
|
||||
{
|
||||
_i = 0;
|
||||
Current = default;
|
||||
}
|
||||
|
||||
public T Current { get; private set; }
|
||||
public T Current => _list[_i];
|
||||
|
||||
object IEnumerator.Current => Current;
|
||||
object? IEnumerator.Current => Current;
|
||||
|
||||
public void Dispose()
|
||||
{
|
||||
|
|
|
@ -4,6 +4,7 @@
|
|||
<TargetFramework>netstandard2.0</TargetFramework>
|
||||
<AllowUnsafeBlocks>true</AllowUnsafeBlocks>
|
||||
<LangVersion>8.0</LangVersion>
|
||||
<Nullable>enable</Nullable>
|
||||
</PropertyGroup>
|
||||
|
||||
<ItemGroup>
|
||||
|
|
|
@ -8,6 +8,7 @@ using SixLabors.ImageSharp.PixelFormats;
|
|||
using System;
|
||||
using System.Drawing;
|
||||
using System.Threading;
|
||||
using Silk.NET.Core;
|
||||
using Image = SixLabors.ImageSharp.Image;
|
||||
|
||||
namespace BlankWindow
|
||||
|
@ -84,7 +85,7 @@ namespace BlankWindow
|
|||
arr = span.ToArray();
|
||||
}
|
||||
|
||||
var icon = new WindowIcon(image.Width, image.Height, arr);
|
||||
var icon = new RawImage(image.Width, image.Height, arr);
|
||||
window.SetWindowIcon(ref icon);
|
||||
Console.WriteLine("Finished loading");
|
||||
}
|
||||
|
|
|
@ -222,12 +222,12 @@ namespace InputTest
|
|||
Console.WriteLine($"M{arg1.Index}> {arg2} up.");
|
||||
}
|
||||
|
||||
private static void MouseOnClick(IMouse arg1, MouseButton arg2)
|
||||
private static void MouseOnClick(IMouse arg1, MouseButton arg2, PointF pos)
|
||||
{
|
||||
Console.WriteLine($"M{arg1.Index}> {arg2} single click.");
|
||||
}
|
||||
|
||||
private static void MouseOnDoubleClick(IMouse arg1, MouseButton arg2)
|
||||
private static void MouseOnDoubleClick(IMouse arg1, MouseButton arg2, PointF pos)
|
||||
{
|
||||
Console.WriteLine($"M{arg1.Index}> {arg2} double click.");
|
||||
}
|
||||
|
|
|
@ -74,7 +74,7 @@ namespace VulkanTriangle
|
|||
private void InitWindow()
|
||||
{
|
||||
var opts = WindowOptions.DefaultVulkan;
|
||||
_window = Window.Create(opts) as IVulkanWindow;
|
||||
_window = Window.Create(opts);
|
||||
if (_window?.VkSurface is null)
|
||||
{
|
||||
throw new NotSupportedException("Windowing platform doesn't support Vulkan.");
|
||||
|
|
|
@ -28,36 +28,46 @@ namespace Silk.NET.Windowing
|
|||
/// Elapsed time in seconds since the View was initialized.
|
||||
/// </summary>
|
||||
double Time { get; }
|
||||
|
||||
/// <summary>
|
||||
/// The size of the framebuffer. May differ from the window size.
|
||||
/// </summary>
|
||||
Size FramebufferSize { get; }
|
||||
|
||||
/// <summary>
|
||||
/// Raised when the window is resized.
|
||||
/// </summary>
|
||||
event Action<Size> Resize;
|
||||
event Action<Size>? Resize;
|
||||
|
||||
/// <summary>
|
||||
/// Raised when the window's framebuffer is resized.
|
||||
/// </summary>
|
||||
event Action<Size>? FramebufferResize;
|
||||
|
||||
/// <summary>
|
||||
/// Raised when the window is about to close.
|
||||
/// </summary>
|
||||
event Action Closing;
|
||||
event Action? Closing;
|
||||
|
||||
/// <summary>
|
||||
/// Raised when the window focus changes.
|
||||
/// </summary>
|
||||
event Action<bool> FocusChanged;
|
||||
event Action<bool>? FocusChanged;
|
||||
|
||||
/// <summary>
|
||||
/// Raised when the window first begins to run.
|
||||
/// </summary>
|
||||
event Action Load;
|
||||
event Action? Load;
|
||||
|
||||
/// <summary>
|
||||
/// Raised when an update should be run.
|
||||
/// </summary>
|
||||
event Action<double> Update;
|
||||
event Action<double>? Update;
|
||||
|
||||
/// <summary>
|
||||
/// Raised when a frame should be rendered.
|
||||
/// </summary>
|
||||
event Action<double> Render;
|
||||
event Action<double>? Render;
|
||||
|
||||
/// <summary>
|
||||
/// Creates the window on the underlying platform.
|
||||
|
@ -99,16 +109,26 @@ namespace Silk.NET.Windowing
|
|||
/// Converts this point to client coordinates.
|
||||
/// </summary>
|
||||
/// <param name="point">The point to transform.</param>
|
||||
/// <returns></returns>
|
||||
/// <returns>The transformed point.</returns>
|
||||
/// <remarks>Expects screen coordinates as input.</remarks>
|
||||
Point PointToClient(Point point);
|
||||
|
||||
/// <summary>
|
||||
/// Converts this point to screen coordinates.
|
||||
/// </summary>
|
||||
/// <param name="point">The point to transform.</param>
|
||||
/// <returns></returns>
|
||||
/// <returns>The transformed point.</returns>
|
||||
/// <remarks>Expects client coordinates as input.</remarks>
|
||||
Point PointToScreen(Point point);
|
||||
|
||||
/// <summary>
|
||||
/// Converts this point to framebuffer coordinates.
|
||||
/// </summary>
|
||||
/// <param name="point">The point to transform.</param>
|
||||
/// <returns>The transformed point.</returns>
|
||||
/// <remarks>Expects client coordinates as input.</remarks>
|
||||
Point PointToFramebuffer(Point point);
|
||||
|
||||
/// <summary>
|
||||
/// Invokes this delegate on the window's main thread, with the provided arguments.
|
||||
/// </summary>
|
||||
|
|
|
@ -1,37 +0,0 @@
|
|||
// This file is part of Silk.NET.
|
||||
//
|
||||
// You may modify and distribute Silk.NET under the terms
|
||||
// of the MIT license. See the LICENSE file for details.
|
||||
|
||||
using System;
|
||||
using Silk.NET.GLFW;
|
||||
|
||||
namespace Silk.NET.Windowing
|
||||
{
|
||||
/// <summary>
|
||||
/// An interface representing a Vulkan window
|
||||
/// </summary>
|
||||
[Obsolete
|
||||
(
|
||||
"IVulkanView is deprecated and will be removed in 2.0, use IView.VkSurface instead. " +
|
||||
"https://github.com/Ultz/Silk.NET/blob/v1.2.0/documentation/deprecation-notices/VulkanViews.md"
|
||||
)]
|
||||
public interface IVulkanView : IView
|
||||
{
|
||||
/// <summary>
|
||||
/// Create a Vulkan surface.
|
||||
/// </summary>
|
||||
/// <param name="instance">The Vulkan instance to create a surface for.</param>
|
||||
/// <param name="allocator">A custom Vulkan allocator. Can be omitted by passing null.</param>
|
||||
/// <typeparam name="T">Allocator type</typeparam>
|
||||
/// <returns>A handle to the Vulkan surface created</returns>
|
||||
unsafe VkHandle CreateSurface<T>(VkHandle instance, T* allocator) where T:unmanaged;
|
||||
|
||||
/// <summary>
|
||||
/// Get the extensions required for Vulkan to work on this platform.
|
||||
/// </summary>
|
||||
/// <param name="count">The number of extensions in the returned array</param>
|
||||
/// <returns>An array of strings, containing names for all required extensions</returns>
|
||||
unsafe char** GetRequiredExtensions(out uint count);
|
||||
}
|
||||
}
|
|
@ -1,21 +0,0 @@
|
|||
// This file is part of Silk.NET.
|
||||
//
|
||||
// You may modify and distribute Silk.NET under the terms
|
||||
// of the MIT license. See the LICENSE file for details.
|
||||
|
||||
using System;
|
||||
|
||||
namespace Silk.NET.Windowing
|
||||
{
|
||||
/// <summary>
|
||||
/// A Vulkan window.
|
||||
/// </summary>
|
||||
[Obsolete
|
||||
(
|
||||
"IVulkanWindow is deprecated and will be removed in 2.0, use IWindow.VkSurface instead. " +
|
||||
"https://github.com/Ultz/Silk.NET/blob/v1.2.0/documentation/deprecation-notices/VulkanViews.md"
|
||||
)]
|
||||
public interface IVulkanWindow : IVulkanView, IWindow
|
||||
{
|
||||
}
|
||||
}
|
|
@ -5,6 +5,7 @@
|
|||
|
||||
using System;
|
||||
using System.Drawing;
|
||||
using Silk.NET.Core;
|
||||
|
||||
namespace Silk.NET.Windowing
|
||||
{
|
||||
|
@ -20,12 +21,12 @@ namespace Silk.NET.Windowing
|
|||
/// <remarks>
|
||||
/// This may be a <see cref="IWindow"/> or a <see cref="IMonitor"/>.
|
||||
/// </remarks>
|
||||
IWindowHost Parent { get; }
|
||||
IWindowHost? Parent { get; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets the monitor on which this window is active.
|
||||
/// </summary>
|
||||
IMonitor Monitor { get; set; }
|
||||
IMonitor? Monitor { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets whether the window has been requested to close.
|
||||
|
@ -35,22 +36,22 @@ namespace Silk.NET.Windowing
|
|||
/// <summary>
|
||||
/// Raised when the window is moved.
|
||||
/// </summary>
|
||||
event Action<Point> Move;
|
||||
event Action<Point>? Move;
|
||||
|
||||
/// <summary>
|
||||
/// Raised when the window state is changed.
|
||||
/// </summary>
|
||||
event Action<WindowState> StateChanged;
|
||||
event Action<WindowState>? StateChanged;
|
||||
|
||||
/// <summary>
|
||||
/// Raised when the user drops files onto the window.
|
||||
/// </summary>
|
||||
event Action<string[]> FileDrop;
|
||||
event Action<string[]>? FileDrop;
|
||||
|
||||
/// <summary>
|
||||
/// Sets the window icons.
|
||||
/// </summary>
|
||||
/// <param name="icons">Either a collection of window icons, or null to set to the default icon.</param>
|
||||
void SetWindowIcon(Span<WindowIcon> icons);
|
||||
void SetWindowIcon(ReadOnlySpan<RawImage> icons);
|
||||
}
|
||||
}
|
|
@ -8,6 +8,8 @@ using System.Buffers;
|
|||
using System.ComponentModel;
|
||||
using System.Diagnostics;
|
||||
using System.Drawing;
|
||||
using System.Numerics;
|
||||
using System.Runtime.CompilerServices;
|
||||
using System.Threading;
|
||||
using Silk.NET.Core.Contexts;
|
||||
|
||||
|
@ -34,7 +36,7 @@ namespace Silk.NET.Windowing.Internals
|
|||
|
||||
// Invocations
|
||||
private readonly ArrayPool<object> _returnArrayPool = ArrayPool<object>.Create();
|
||||
private PendingInvocation[] _pendingInvocations;
|
||||
private PendingInvocation[]? _pendingInvocations;
|
||||
private int _rented;
|
||||
|
||||
// Ensure we keep SwapInterval up-to-date
|
||||
|
@ -65,6 +67,7 @@ namespace Silk.NET.Windowing.Internals
|
|||
public abstract bool IsClosing { get; }
|
||||
public abstract VideoMode VideoMode { get; }
|
||||
public abstract bool IsEventDriven { get; set; }
|
||||
public abstract Size FramebufferSize { get; }
|
||||
public abstract void DoEvents();
|
||||
public abstract void ContinueEvents();
|
||||
public abstract void Dispose();
|
||||
|
@ -75,12 +78,13 @@ namespace Silk.NET.Windowing.Internals
|
|||
protected abstract void UnregisterCallbacks();
|
||||
|
||||
// Events
|
||||
public abstract event Action<Size> Resize;
|
||||
public abstract event Action Closing;
|
||||
public abstract event Action<bool> FocusChanged;
|
||||
public event Action Load;
|
||||
public event Action<double> Update;
|
||||
public event Action<double> Render;
|
||||
public abstract event Action<Size>? Resize;
|
||||
public abstract event Action<Size>? FramebufferResize;
|
||||
public abstract event Action? Closing;
|
||||
public abstract event Action<bool>? FocusChanged;
|
||||
public event Action? Load;
|
||||
public event Action<double>? Update;
|
||||
public event Action<double>? Render;
|
||||
|
||||
// Lifetime controls
|
||||
public void Initialize()
|
||||
|
@ -176,13 +180,55 @@ namespace Silk.NET.Windowing.Internals
|
|||
_optionsCache.VSync = value;
|
||||
}
|
||||
}
|
||||
|
||||
// Misc implementations
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining | (MethodImplOptions)512)]
|
||||
public Point PointToFramebuffer(Point point)
|
||||
{
|
||||
// TODO this monstrosity will be gone once Silk.NET.Maths is in
|
||||
if (Vector.IsHardwareAccelerated && Vector<int>.Count >= 2)
|
||||
{
|
||||
#if NETSTANDARD2_1
|
||||
// ReSharper disable SuggestVarOrType_Elsewhere
|
||||
Span<int> framebufferSizeElements = stackalloc int[Vector<int>.Count];
|
||||
Unsafe.As<int, Size>(ref framebufferSizeElements[0]) = FramebufferSize;
|
||||
var framebufferSize = new Vector<int>(framebufferSizeElements);
|
||||
Span<int> sizeElements = stackalloc int[Vector<int>.Count];
|
||||
Unsafe.As<int, Size>(ref sizeElements[0]) = Size;
|
||||
var size = new Vector<int>(sizeElements);
|
||||
Span<int> pointElements = stackalloc int[Vector<int>.Count];
|
||||
Unsafe.As<int, Point>(ref pointElements[0]) = point;
|
||||
var thePoint = new Vector<int>(pointElements);
|
||||
// ReSharper restore SuggestVarOrType_Elsewhere
|
||||
#else
|
||||
var c = Vector<int>.Count;
|
||||
var a = new int[c * 3];
|
||||
Unsafe.As<int, Size>(ref a[0]) = FramebufferSize;
|
||||
Unsafe.As<int, Size>(ref a[c]) = Size;
|
||||
Unsafe.As<int, Point>(ref a[c * 2]) = point;
|
||||
var framebufferSize = new Vector<int>(a, 0);
|
||||
var size = new Vector<int>(a, c);
|
||||
var thePoint = new Vector<int>(a, c * 2);
|
||||
#endif
|
||||
thePoint = Vector.Multiply(thePoint, Vector.Divide(framebufferSize, size));
|
||||
return new Point(thePoint[0], thePoint[1]);
|
||||
}
|
||||
|
||||
var fSize = FramebufferSize;
|
||||
var aSize = Size;
|
||||
return new Point
|
||||
{
|
||||
X = point.X * (fSize.Width / aSize.Width),
|
||||
Y = point.Y * (fSize.Height / aSize.Height)
|
||||
};
|
||||
}
|
||||
|
||||
// Invoke system
|
||||
public object Invoke(Delegate d, params object[] args)
|
||||
{
|
||||
var rentalIndex = Interlocked.Increment(ref _rented) - 1;
|
||||
EnsureArrayIsReady(rentalIndex);
|
||||
ref var x = ref _pendingInvocations[rentalIndex];
|
||||
ref var x = ref _pendingInvocations![rentalIndex];
|
||||
x.Delegate = d;
|
||||
x.Data = args;
|
||||
x.ResetEvent.Reset();
|
||||
|
@ -197,11 +243,16 @@ namespace Silk.NET.Windowing.Internals
|
|||
|
||||
public void DoInvokes()
|
||||
{
|
||||
if (_pendingInvocations is null)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
var completed = 0;
|
||||
for (var i = 0; i < _rented + completed && i < _pendingInvocations.Length; i++)
|
||||
{
|
||||
ref var invocation = ref _pendingInvocations[i];
|
||||
if (invocation.IsComplete)
|
||||
if (invocation.IsComplete || invocation.Delegate is null)
|
||||
{
|
||||
completed++;
|
||||
}
|
||||
|
@ -239,7 +290,7 @@ namespace Silk.NET.Windowing.Internals
|
|||
|
||||
var na = new PendingInvocation[finalSize];
|
||||
var og = Interlocked.Exchange(ref _pendingInvocations, na);
|
||||
og.CopyTo(na, 0);
|
||||
og?.CopyTo(na, 0);
|
||||
for (var i = 0; i < na.Length; i++)
|
||||
{
|
||||
na[i].ResetEvent ??= new ManualResetEventSlim();
|
||||
|
@ -249,8 +300,8 @@ namespace Silk.NET.Windowing.Internals
|
|||
private struct PendingInvocation
|
||||
{
|
||||
public bool IsComplete { get; set; }
|
||||
public Delegate Delegate { get; set; }
|
||||
public object[] Data { get; set; }
|
||||
public Delegate? Delegate { get; set; }
|
||||
public object[]? Data { get; set; }
|
||||
public ManualResetEventSlim ResetEvent { get; set; }
|
||||
}
|
||||
}
|
||||
|
|
|
@ -5,6 +5,7 @@
|
|||
|
||||
using System;
|
||||
using System.Drawing;
|
||||
using Silk.NET.Core;
|
||||
|
||||
|
||||
namespace Silk.NET.Windowing.Internals
|
||||
|
@ -38,15 +39,15 @@ namespace Silk.NET.Windowing.Internals
|
|||
protected abstract void CoreInitialize(WindowOptions opts);
|
||||
|
||||
// Events
|
||||
public abstract event Action<Point> Move;
|
||||
public abstract event Action<WindowState> StateChanged;
|
||||
public abstract event Action<string[]> FileDrop;
|
||||
public abstract event Action<Point>? Move;
|
||||
public abstract event Action<WindowState>? StateChanged;
|
||||
public abstract event Action<string[]>? FileDrop;
|
||||
|
||||
// Other APIs implemented abstractly
|
||||
public abstract IWindow CreateWindow(WindowOptions opts);
|
||||
public abstract IWindowHost Parent { get; }
|
||||
public abstract IMonitor Monitor { get; set; }
|
||||
public abstract void SetWindowIcon(Span<WindowIcon> icons);
|
||||
public abstract IWindowHost? Parent { get; }
|
||||
public abstract IMonitor? Monitor { get; set; }
|
||||
public abstract void SetWindowIcon(ReadOnlySpan<RawImage> icons);
|
||||
|
||||
// Cache updates for dervied classes
|
||||
protected void UpdatePosition(Point point) => _optionsCache.Position = point;
|
||||
|
|
|
@ -1,10 +1,11 @@
|
|||
<Project Sdk="Microsoft.NET.Sdk">
|
||||
|
||||
<PropertyGroup>
|
||||
<TargetFramework>netstandard2.0</TargetFramework>
|
||||
<TargetFrameworks>netstandard2.0;netstandard2.1</TargetFrameworks>
|
||||
<LangVersion>8.0</LangVersion>
|
||||
<AllowUnsafeBlocks>true</AllowUnsafeBlocks>
|
||||
<RootNamespace>Silk.NET.Windowing</RootNamespace>
|
||||
<Nullable>enable</Nullable>
|
||||
</PropertyGroup>
|
||||
|
||||
<ItemGroup>
|
||||
|
|
|
@ -1,4 +1,5 @@
|
|||
<wpf:ResourceDictionary xml:space="preserve" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" xmlns:s="clr-namespace:System;assembly=mscorlib" xmlns:ss="urn:shemas-jetbrains-com:settings-storage-xaml" xmlns:wpf="http://schemas.microsoft.com/winfx/2006/xaml/presentation">
|
||||
<s:Boolean x:Key="/Default/CodeInspection/NamespaceProvider/NamespaceFoldersToSkip/=enums/@EntryIndexedValue">True</s:Boolean>
|
||||
<s:Boolean x:Key="/Default/CodeInspection/NamespaceProvider/NamespaceFoldersToSkip/=interfaces/@EntryIndexedValue">True</s:Boolean></wpf:ResourceDictionary>
|
||||
<s:Boolean x:Key="/Default/CodeInspection/NamespaceProvider/NamespaceFoldersToSkip/=structs/@EntryIndexedValue">True</s:Boolean></wpf:ResourceDictionary>
|
||||
<s:Boolean x:Key="/Default/CodeInspection/NamespaceProvider/NamespaceFoldersToSkip/=interfaces/@EntryIndexedValue">True</s:Boolean>
|
||||
<s:Boolean x:Key="/Default/CodeInspection/NamespaceProvider/NamespaceFoldersToSkip/=structs/@EntryIndexedValue">True</s:Boolean></wpf:ResourceDictionary>
|
||||
|
|
@ -1,21 +0,0 @@
|
|||
// This file is part of Silk.NET.
|
||||
//
|
||||
// You may modify and distribute Silk.NET under the terms
|
||||
// of the MIT license. See the LICENSE file for details.
|
||||
|
||||
namespace Silk.NET.Windowing
|
||||
{
|
||||
public readonly struct WindowIcon
|
||||
{
|
||||
public WindowIcon(int width, int height, byte[] rgbaPixels)
|
||||
{
|
||||
Pixels = rgbaPixels;
|
||||
Width = width;
|
||||
Height = height;
|
||||
}
|
||||
|
||||
public int Width { get; }
|
||||
public int Height { get; }
|
||||
public byte[] Pixels { get; }
|
||||
}
|
||||
}
|
|
@ -4,6 +4,7 @@
|
|||
// of the MIT license. See the LICENSE file for details.
|
||||
|
||||
using System;
|
||||
using Silk.NET.Core;
|
||||
|
||||
namespace Silk.NET.Windowing
|
||||
{
|
||||
|
@ -72,7 +73,11 @@ namespace Silk.NET.Windowing
|
|||
/// </summary>
|
||||
/// <param name="window">The window.</param>
|
||||
/// <param name="icon">The icon to set.</param>
|
||||
public static void SetWindowIcon(this IWindow window, ref WindowIcon icon) => window.SetWindowIcon
|
||||
public static void SetWindowIcon(this IWindow window, ref RawImage icon) => window.SetWindowIcon
|
||||
#if NETSTANDARD2_1
|
||||
(System.Runtime.InteropServices.MemoryMarshal.CreateReadOnlySpan(ref icon, 1));
|
||||
#else
|
||||
(new[] {icon});
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
|
|
@ -8,7 +8,6 @@ using System.Runtime.CompilerServices;
|
|||
using Silk.NET.GLFW;
|
||||
using Silk.NET.Windowing;
|
||||
using Silk.NET.Windowing.Glfw;
|
||||
using Silk.NET.Windowing.Internals;
|
||||
|
||||
[assembly: InternalsVisibleTo("Silk.NET.Input.Glfw")]
|
||||
[assembly: WindowPlatform(typeof(GlfwPlatform))]
|
||||
|
@ -20,8 +19,6 @@ namespace Silk.NET.Windowing.Glfw
|
|||
/// </summary>
|
||||
internal class GlfwPlatform : IWindowPlatform
|
||||
{
|
||||
public GlfwPlatform(){ }
|
||||
|
||||
/// <inheritdoc />
|
||||
public bool IsViewOnly { get; } = false;
|
||||
|
||||
|
|
|
@ -5,7 +5,9 @@
|
|||
|
||||
using System;
|
||||
using System.Drawing;
|
||||
using System.Runtime.CompilerServices;
|
||||
using System.Runtime.InteropServices;
|
||||
using Silk.NET.Core;
|
||||
using Silk.NET.Core.Contexts;
|
||||
using Silk.NET.GLFW;
|
||||
using Silk.NET.Windowing.Internals;
|
||||
|
@ -17,23 +19,25 @@ namespace Silk.NET.Windowing.Glfw
|
|||
private readonly GLFW.Glfw _glfw;
|
||||
private WindowHandle* _glfwWindow;
|
||||
private string _localTitleCache; // glfw doesn't let us get the window title.
|
||||
private readonly GlfwWindow _parent;
|
||||
private readonly GlfwMonitor _initialMonitor;
|
||||
private readonly GlfwWindow? _parent;
|
||||
private readonly GlfwMonitor? _initialMonitor;
|
||||
|
||||
// Callbacks
|
||||
private GlfwCallbacks.WindowPosCallback _onMove;
|
||||
private GlfwCallbacks.WindowSizeCallback _onResize;
|
||||
private GlfwCallbacks.DropCallback _onFileDrop;
|
||||
private GlfwCallbacks.WindowCloseCallback _onClosing;
|
||||
private GlfwCallbacks.WindowFocusCallback _onFocusChanged;
|
||||
private GlfwCallbacks.WindowIconifyCallback _onMinimized;
|
||||
private GlfwCallbacks.WindowMaximizeCallback _onMaximized;
|
||||
private GlfwCallbacks.WindowPosCallback? _onMove;
|
||||
private GlfwCallbacks.WindowSizeCallback? _onResize;
|
||||
private GlfwCallbacks.FramebufferSizeCallback? _onFramebufferResize;
|
||||
private GlfwCallbacks.DropCallback? _onFileDrop;
|
||||
private GlfwCallbacks.WindowCloseCallback? _onClosing;
|
||||
private GlfwCallbacks.WindowFocusCallback? _onFocusChanged;
|
||||
private GlfwCallbacks.WindowIconifyCallback? _onMinimized;
|
||||
private GlfwCallbacks.WindowMaximizeCallback? _onMaximized;
|
||||
|
||||
public GlfwWindow(WindowOptions optionsCache, GlfwWindow parent, GlfwMonitor monitor) : base(optionsCache)
|
||||
public GlfwWindow(WindowOptions optionsCache, GlfwWindow? parent, GlfwMonitor? monitor) : base(optionsCache)
|
||||
{
|
||||
_glfw = GlfwProvider.GLFW.Value;
|
||||
_parent = parent;
|
||||
_initialMonitor = monitor;
|
||||
_localTitleCache = optionsCache.Title;
|
||||
}
|
||||
|
||||
protected override Size CoreSize
|
||||
|
@ -197,6 +201,15 @@ namespace Silk.NET.Windowing.Glfw
|
|||
!(_initialMonitor is null) ? _initialMonitor.Handle : null,
|
||||
null
|
||||
);
|
||||
|
||||
if (opts.IsVisible)
|
||||
{
|
||||
_glfw.ShowWindow(_glfwWindow);
|
||||
}
|
||||
else
|
||||
{
|
||||
_glfw.HideWindow(_glfwWindow);
|
||||
}
|
||||
|
||||
if (opts.API.API == ContextAPI.OpenGL || opts.API.API == ContextAPI.OpenGLES)
|
||||
{
|
||||
|
@ -206,10 +219,10 @@ namespace Silk.NET.Windowing.Glfw
|
|||
GLFW.Glfw.ThrowExceptions();
|
||||
}
|
||||
|
||||
public override event Action<Point> Move;
|
||||
public override event Action<WindowState> StateChanged;
|
||||
public override event Action<string[]> FileDrop;
|
||||
public override void SetWindowIcon(Span<WindowIcon> icons)
|
||||
public override event Action<Point>? Move;
|
||||
public override event Action<WindowState>? StateChanged;
|
||||
public override event Action<string[]>? FileDrop;
|
||||
public override void SetWindowIcon(ReadOnlySpan<RawImage> icons)
|
||||
{
|
||||
if (!IsInitialized)
|
||||
{
|
||||
|
@ -227,17 +240,14 @@ namespace Silk.NET.Windowing.Glfw
|
|||
{
|
||||
var icon = icons[i];
|
||||
// ReSharper disable once StackAllocInsideLoop
|
||||
var iconMemory = stackalloc byte[icon.Pixels.Length];
|
||||
Span<byte> iconMemory = stackalloc byte[icon.Pixels.Length];
|
||||
images[i] = new Image
|
||||
{
|
||||
Width = icon.Width, Height = icon.Height,
|
||||
Pixels = iconMemory
|
||||
Pixels = (byte*)Unsafe.AsPointer(ref iconMemory[0])
|
||||
};
|
||||
|
||||
for (var j = 0; j < icon.Pixels.Length; j++)
|
||||
{
|
||||
iconMemory[j] = icon.Pixels[j];
|
||||
}
|
||||
|
||||
icon.Pixels.Span.CopyTo(iconMemory);
|
||||
}
|
||||
|
||||
_glfw.SetWindowIcon(_glfwWindow, icons.Length, images);
|
||||
|
@ -247,8 +257,8 @@ namespace Silk.NET.Windowing.Glfw
|
|||
|
||||
public override IWindow CreateWindow(WindowOptions opts) => new GlfwWindow(opts, this, null);
|
||||
|
||||
public override IWindowHost Parent => (IWindowHost)_parent ?? Monitor;
|
||||
public override IMonitor Monitor
|
||||
public override IWindowHost? Parent => (IWindowHost?)_parent ?? Monitor;
|
||||
public override IMonitor? Monitor
|
||||
{
|
||||
get
|
||||
{
|
||||
|
@ -345,6 +355,15 @@ namespace Silk.NET.Windowing.Glfw
|
|||
=> IsInitialized ? CachedVideoMode = Monitor?.VideoMode ?? CachedVideoMode : CachedVideoMode;
|
||||
public override bool IsEventDriven { get; set; }
|
||||
|
||||
public override Size FramebufferSize
|
||||
{
|
||||
get
|
||||
{
|
||||
_glfw.GetFramebufferSize(_glfwWindow, out var width, out var height);
|
||||
return new Size(width, height);
|
||||
}
|
||||
}
|
||||
|
||||
public override void DoEvents()
|
||||
{
|
||||
if (IsEventDriven)
|
||||
|
@ -388,6 +407,11 @@ namespace Silk.NET.Windowing.Glfw
|
|||
Resize?.Invoke(size);
|
||||
};
|
||||
|
||||
_onFramebufferResize = (window, width, height) =>
|
||||
{
|
||||
FramebufferResize?.Invoke(new Size(width, height));
|
||||
};
|
||||
|
||||
_onClosing = window => Closing?.Invoke();
|
||||
|
||||
_onFocusChanged = (window, isFocused) => FocusChanged?.Invoke(isFocused);
|
||||
|
@ -473,6 +497,7 @@ namespace Silk.NET.Windowing.Glfw
|
|||
_glfw.SetWindowFocusCallback(_glfwWindow, _onFocusChanged);
|
||||
_glfw.SetWindowIconifyCallback(_glfwWindow, _onMinimized);
|
||||
_glfw.SetWindowMaximizeCallback(_glfwWindow, _onMaximized);
|
||||
_glfw.SetFramebufferSizeCallback(_glfwWindow, _onFramebufferResize);
|
||||
_glfw.SetDropCallback(_glfwWindow, _onFileDrop);
|
||||
GLFW.Glfw.ThrowExceptions();
|
||||
}
|
||||
|
@ -489,14 +514,16 @@ namespace Silk.NET.Windowing.Glfw
|
|||
_glfw.GcUtility.Unpin(_onMinimized);
|
||||
_glfw.GcUtility.Unpin(_onMove);
|
||||
_glfw.GcUtility.Unpin(_onResize);
|
||||
_glfw.GcUtility.Unpin(_onFramebufferResize);
|
||||
_glfw.GcUtility.Unpin(_onFileDrop);
|
||||
_glfw.GcUtility.Unpin(_onFocusChanged);
|
||||
}
|
||||
}
|
||||
|
||||
public override event Action<Size> Resize;
|
||||
public override event Action Closing;
|
||||
public override event Action<bool> FocusChanged;
|
||||
public override event Action<Size>? Resize;
|
||||
public override event Action<Size>? FramebufferResize;
|
||||
public override event Action? Closing;
|
||||
public override event Action<bool>? FocusChanged;
|
||||
|
||||
~GlfwWindow()
|
||||
{
|
||||
|
|
|
@ -3,6 +3,7 @@
|
|||
<PropertyGroup>
|
||||
<TargetFramework>netstandard2.0</TargetFramework>
|
||||
<AllowUnsafeBlocks>true</AllowUnsafeBlocks>
|
||||
<Nullable>enable</Nullable>
|
||||
</PropertyGroup>
|
||||
|
||||
<ItemGroup>
|
||||
|
|
Загрузка…
Ссылка в новой задаче