* 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:
Dylan Perks 2020-08-02 21:55:12 +01:00 коммит произвёл GitHub
Родитель 1d0a824124
Коммит fa2c8b8345
Не найден ключ, соответствующий данной подписи
Идентификатор ключа GPG: 4AEE18F83AFDEB23
50 изменённых файлов: 595 добавлений и 576 удалений

2
.github/workflows/build.yml поставляемый
Просмотреть файл

@ -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:

2
.github/workflows/deploy.yml поставляемый
Просмотреть файл

@ -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

1
.gitignore поставляемый
Просмотреть файл

@ -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>