-
-
Notifications
You must be signed in to change notification settings - Fork 440
Multi-Backend Input for Silk.NET 3.0 #554
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Merged
Merged
Changes from 10 commits
Commits
Show all changes
17 commits
Select commit
Hold shift + click to select a range
1e24a31
Create Proposal - Multi-Backend Input.md
Perksey 2244cc6
Update Proposal - Multi-Backend Input.md
Perksey 5d1badb
Update Proposal - Multi-Backend Input.md
Perksey 95d2f06
Update Proposal - Multi-Backend Input.md
Perksey 944ca40
Merge branch 'proposal/all-3.0-proposals' into proposal/3.0-input-llapi
Perksey 8b7b0b1
Update documentation/proposals/Proposal - Multi-Backend Input.md
Perksey 43dcd77
Update Proposal - Multi-Backend Input.md
Perksey 4b227fe
Update Proposal - Multi-Backend Input.md
Perksey e0ce2e4
Update Proposal - Multi-Backend Input.md
Perksey 275156c
Update Proposal - Multi-Backend Input.md
Perksey 46efdf1
Update Proposal - Multi-Backend Input.md
Perksey 66cda42
Update Proposal - Multi-Backend Input.md
Perksey 5cef994
Update Proposal - Multi-Backend Input.md
Perksey 436a03e
Update Proposal - Multi-Backend Input.md
Perksey 209d4dd
Update documentation/proposals/Proposal - Multi-Backend Input.md
Perksey e2e14dd
Update Proposal - Multi-Backend Input.md
Perksey fcb04e0
Update Proposal - Multi-Backend Input.md
Perksey File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
190 changes: 190 additions & 0 deletions
190
documentation/proposals/Proposal - Multi-Backend Input.md
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,190 @@ | ||
| # Summary | ||
| Proposal API for backend-agnostic, refactored Input via keyboards, mice, and controllers. | ||
|
|
||
| # Contributors | ||
| - Dylan Perks (@Perksey) | ||
|
|
||
| # Current Status | ||
| - [x] Proposed | ||
| - [ ] Discussed with Working Group | ||
| - [ ] Approved | ||
| - [ ] Implemented | ||
|
|
||
| # Design Decisions | ||
| - This proposal refactors the internals of the Input API to be less tied to a single backend, and instead allow multiple backends to be added and removed from an input context at will. | ||
| - This proposal aims to keep the look and feel of the Input APIs intended for general consumption similar to that of 2.0. | ||
| - This proposal assumes knowledge of the following proposals: | ||
| - Windowing 3.0 | ||
| - Input | ||
| - Enhanced Input Events | ||
| - This proposal also assumes knowledge of 2.0's Input APIs as it is only a refactor and not a complete redesign of the API as in other proposals. The most noticable differences between the design of Input 2.0 and Input 3.0 are: | ||
| - Input no longer has a hard bond to Windowing. The integration will remain the same to the end user but will use Source Generators, more on that later. | ||
| - Input contexts are no longer interfaces, they are instead classes which contain input backends. | ||
|
|
||
| ## Reference Implementation | ||
|
|
||
| Similar to Windowing 3.0, a reference implementation will be included in the main `Silk.NET.Input` package which uses the same API or family of APIs as Windowing. This will be exposed via the `InputBackend` class. The `InputBackend` class contains a static `Create` method which accepts the native handle for the input context on the particular underlying API i.e. on GLFW this handle represents a `GLFWwindow*`. This may be subject to change. | ||
|
|
||
| ## Source Generator | ||
|
|
||
| Alongside the input package there will be a source generator (shipped in a `Silk.NET.Input.Roslyn` NuGet package, which is referenced by the main input package). This source generator will be very small, but it allows us to create a link between windowing and input at compile time without a hard reference. | ||
|
|
||
| If the source generator detects that both `Silk.NET.Input` and `Silk.NET.Windowing` are referenced, code with the following API surface will be injected into the assembly: | ||
| ```cs | ||
| namespace Silk.NET.Input | ||
| { | ||
| internal static class InputSurfaceExtensions // internal to avoid conflicts with other assemblies | ||
| { | ||
| public static InputContext CreateInput(this ISurface surface); | ||
| } | ||
| } | ||
| ``` | ||
|
|
||
| The `CreateInput` method will use the surface, obtain its platform data (i.e. by using something like `IGlfwPlatformData`), and then feed that into `InputBackend.Create`. The returned `InputContext` will be configured to have the returned `IInputBackend` as a backend. This method will also appropriately bind the `ISurface.Update` callback: | ||
| - The delegate passed in the `onActivated` parameter of `InputBackend.Create` will bind the `IInputBackend.Update` method to run in the `ISurface.Update` callback. | ||
HurricanKai marked this conversation as resolved.
Outdated
Show resolved
Hide resolved
|
||
| - The delegate passed in the `onDeactivated` parameter of `InputBackend.Create` will unbind the `ISurface.Update` callback. | ||
| - These delegates must be called by the reference implementation in its `IInputBackend.Activate` and `IInputBackend.Deactivate` methods (respectively) | ||
HurricanKai marked this conversation as resolved.
Outdated
Show resolved
Hide resolved
|
||
| - The `IInputBackend.Activate` and `IInputBackend.Deactivate` methods must be called by the `InputContext.Add` and `InputContext.Remove` methods (respectively) | ||
HurricanKai marked this conversation as resolved.
Outdated
Show resolved
Hide resolved
|
||
|
|
||
| The API surface for this is defined later in the Proposed API section. | ||
|
|
||
| One instance of an `IInputBackend` can only belong to one input context at a time. If multiple input contexts are in use, multiple backend instances should also be used. An input context is set as active/in use by a context using the `Activate` and `Deactivate` methods. `Activate` should throw an exception if already activated, and `Deactivate` should throw an exception if not already activated. Once deactivated, an input backend can be reactivated. | ||
HurricanKai marked this conversation as resolved.
Outdated
Show resolved
Hide resolved
|
||
|
|
||
| **KEY POINT FOR WORKING GROUP**: The Windowing-Input integration mandates the use of source generators. Is this ok? | ||
|
|
||
| # Proposed API | ||
|
|
||
| ```diff | ||
| namespace Silk.NET.Input | ||
| { | ||
| - public interface IInputPlatform | ||
| - { | ||
| - bool IsApplicable(IView view); | ||
| - IInputContext CreateInput(IView view); | ||
| - } | ||
| } | ||
| ``` | ||
|
|
||
| ```diff | ||
| namespace Silk.NET.Input | ||
| { | ||
| + /// <summary> | ||
| + /// Encapsulates input devices sourced from input backends. | ||
| + /// </summary> | ||
| - public interface IInputContext : IDisposable | ||
| + public sealed class InputContext : IDisposable | ||
| { | ||
| - nint Handle { get; } | ||
| IReadOnlyList<IGamepad> Gamepads { get; } | ||
| IReadOnlyList<IJoystick> Joysticks { get; } | ||
| IReadOnlyList<IKeyboard> Keyboards { get; } | ||
| IReadOnlyList<IMouse> Mice { get; } | ||
| IReadOnlyList<IInputDevice> OtherDevices { get; } | ||
| + | ||
| + /// <summary> | ||
| + /// Gets a list of backends from which all input devices on this input context are sourced. | ||
| + /// </summary> | ||
| + IReadOnlyList<IInputBackend> Backends { get; } | ||
| event Action<IInputDevice, bool>? ConnectionChanged; | ||
| + | ||
| + /// <summary> | ||
| + /// Adds the given backend to the list of <see cref="Backends" />. | ||
| + /// </summary> | ||
| + void Add(IInputBackend backend); | ||
| + | ||
| + /// <summary> | ||
| + /// Removes the given backend from the list of <see cref="Backends" />. | ||
| + /// </summary> | ||
| + void Remove(IInputBackend backend); | ||
| + | ||
| + /// <summary> | ||
| + /// Updates all input data on all backends. | ||
| + /// </summary> | ||
| + void Update(); | ||
| } | ||
| } | ||
| ``` | ||
|
|
||
| ```diff | ||
| namespace Silk.NET.Input | ||
| { | ||
| + /// <summary> | ||
| + /// Represents an input backend from which input devices can be retrieved. | ||
| + /// </summary> | ||
| + public interface IInputBackend | ||
| + { | ||
| + /// <summary> | ||
| + /// Gets all connected devices recognised by this backend. | ||
| + /// </summary> | ||
| + IReadOnlyList<IInputDevice> ConnectedDevices { get; } | ||
| + | ||
| + /// <summary> | ||
| + /// Raised when an input device is connected or disconnected. | ||
| + /// </summary> | ||
| + event Action<IInputDevice, bool>? ConnectionChanged; | ||
| + | ||
| + /// <summary> | ||
| + /// Updates this backend's input data. | ||
| + /// </summary> | ||
| + /// <remarks> | ||
| + /// Input events and changes are permitted to occur outside of this method. | ||
| + /// </remarks> | ||
| + void Update(); | ||
| + | ||
| + /// <summary> | ||
| + /// Activates this input backend and runs any necessary prerequisites to collecting input data. | ||
| + /// Once activated, <see cref="Deactivate" /> must be used before the backend can be activated again. | ||
| + /// </summary> | ||
| + /// <remarks> | ||
| + /// Called by <see cref="InputContext.Add" /> | ||
| + /// </remarks> | ||
| + void Activate(); | ||
| + | ||
| + /// <summary> | ||
| + /// Deactivates this input backend and destroys/disables any resources responsible for collecting input data. | ||
| + /// Once deactivated, <see cref="Activate" /> can be used to activate the backend again. | ||
| + /// </summary> | ||
| + /// <remarks> | ||
| + /// Called by <see cref="InputContext.Remove" />. | ||
| + /// </remarks> | ||
| + void Deactivate(); | ||
| + } | ||
| } | ||
| ``` | ||
|
|
||
| ```diff | ||
| namespace Silk.NET.Input | ||
| { | ||
| - public static class InputWindowExtensions | ||
| - { | ||
| - // ... | ||
| - } | ||
| } | ||
| ``` | ||
|
|
||
| ```diff | ||
| namespace Silk.NET.Input | ||
| { | ||
| + /// <summary> | ||
| + /// Represents the out-of-the-box input backend, which uses a native API to retrieve input backends using a native handle. | ||
| + /// </summary> | ||
| + /// <remarks> | ||
| + /// On desktop, this uses GLFW. | ||
HurricanKai marked this conversation as resolved.
Show resolved
Hide resolved
|
||
| + /// </remarks> | ||
| + public static class InputBackend | ||
| + { | ||
| + /// <summary> | ||
| + /// Creates an instance of the out-of-the-box input backend, which uses a native API to retrieve input backends using | ||
| + /// the given native handle, optionally calling the given delegates when the input backend is activated and deactivated. | ||
| + /// </summary> | ||
| + /// <param name="handle">The native handle created/sourced from the underlying native API used by this input backend.</param> | ||
| + /// <param name="onActivate">A delegate to be called when the context is activated. May be null.</param> | ||
| + /// <param name="onDeactivate">A delegate to be called when the context is deactivated. May be null.</param> | ||
HurricanKai marked this conversation as resolved.
Outdated
Show resolved
Hide resolved
|
||
| + /// <remarks> | ||
| + /// This method is implicitly called by the Windowing-Input integration. <br /> | ||
| + /// On desktop, this uses GLFW. The handle refers to a <c>GLFWwindow*</c> if GLFW is in use. | ||
| + /// </remarks> | ||
| + public static unsafe IInputBackend Create(void* handle, Action? onActivate = null, Action? onDeactivate = null); | ||
HurricanKai marked this conversation as resolved.
Outdated
Show resolved
Hide resolved
|
||
| + } | ||
| } | ||
| ``` | ||
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Why in a separate package? at this point I'm pretty confident one can ship both in one package.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I'm not entirely convinced this is possible, they're structured differently and even if we can NuGet will not be able to distinguish dependencies.