-
-
Notifications
You must be signed in to change notification settings - Fork 420
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
Add initial axis input proposal draft #2415
base: main
Are you sure you want to change the base?
Conversation
@dotnet-policy-service agree |
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 love this proposal!
public class DualsenseDevice : IAxisDevice | ||
{ | ||
IReadOnlyList<AxisDescription> | ||
private static readonly IReadOnlyList<AxisDescription> Axes = |
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 know this is INFORMATIVE TEXT but... triggers? Only reason I mention it is because it's quite pertinent for DualSense specifically. Feel free to ignore this comment though as it may open irrelevant discussions now I mention it (namely application-controlled axes like the haptic feedback)
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 haven't yet thought of any sort of API for axis output yet. my thoughts were outputs could be a non-breaking extension to this API as you mightve guessed - lots of things to consider there (and potentially lots of input-related expansions too e.g. microphone/audio out, LEDs, etc). i have no problem re-visiting this to properly complete the axis list though
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 do think it would be a shame to accept the proposal not having a path to implementing the base proposal in terms of this proposal, as that is ultimately one of the main goals.
A lot of the benefits we get from this axis model still exist without that mind e.g. it makes developing an input action model a lot easier, but we should have a clear strategy for getting to the future we want. And if we accept this proposal without everything, we open up opportunities to have fragmented implementations given that we'd have to care about backwards compatibility if it does get implemented without the other proposals being approved.
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.
lemme stew a bit. i just dont want to paint ourselves into a corner with device outputs (since some may not be very simple - e.g. streaming outputs that arent abstractable to a floating point value)
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 added a draft of an idea to the end of the proposal
/// <summary> | ||
/// An interface for handling deadzones in different ways | ||
/// </summary> | ||
public interface IDeadzoneHandler |
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.
Sceptical about calling this IDeadzoneHandler
given that in our input API "handlers" usually refer to our actor-like model for handling input events.
Maybe IDeadzoneDeterminant
, or maybe call this IDeadzone
and rename Deadzone
to DeadzoneBounds
? Or something else?
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.
the naming was an attempt to keep the API consistent with how people will be used to handling input events, though if this doesn't actually follow the model of the others then I'm totally down to change the name. Though not crazy about those names in particular bc i think it's less clear
we can shop it with The Gang? ¯_(ツ)_/¯
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.
Will discuss in meeting.
Co-authored-by: Dylan Perks <[email protected]>
Co-authored-by: Dylan Perks <[email protected]>
Co-authored-by: Dylan Perks <[email protected]>
…xisGroupType.Position2D and 3D
this feedback was more-or-less answered by myself in the axis group priority section. if we need or would like to provide anything more specific, it could be an extension method
/// Represents the state of a single axis | ||
/// </summary> | ||
/// <param name="IsActive">True if the axis is currently in use / actively updated (required to be true if axis is not <see cref="AxisTrait.Dynamic"/>) | ||
public readonly record struct AxisState(IAxisDevice Device, AxisDescription Description, float Value, bool IsActive = true); |
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.
Should IsActive
be in AxisDescription
? Or more specifically, should this be queryable outside of a handler method call?
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.
Or perhaps RawValues should be replaced with an AxisState IReadOnlyList that produces these structs on the fly?
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 like the idea of putting it in AxisDescription
, though I'd really like to avoid the scenario where a "fixed" axis is marked as "IsActive = false" post-validation. currently theres no defense against this anyway, but it could create ideas.
though it could be a nice way to say "hey my X button is broken, can we not?" so in that case im actually gonna update this to be in the AxisDefinition and allow IsActive (w/ potential rename) to be used universally. we're probably never going to do that, but ¯_(ツ)_/¯
/// </summary> | ||
/// <param name="index">The index of the <see cref="OutputDescription"/> in <see cref="Outputs"/></param> | ||
/// <param name="values">A pointer to the value(s) to be set</param> | ||
public void SetOutput<T>(int index, T* values, int count = 1) where T : unmanaged => throw new NotImplementedException(); |
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.
Can we change this to be ReadOnlySpan, perhaps with a DIM that implicitly creates a 1-element span from a single ref readonly
parameter?
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.
funny i actually changed it from a span to a pointer when writing this - happy to change it back to appease my paranoid ass
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 think if we're splitting this up into outputs vs output groups then we should likely have a single output be a single float or a single T (with the T path being try-based to enable extension detection, again we should reserve the right to define these extensions as we see fit given that they're not the happy path, and that not everything is cleanly representable as a float.
/// specific trigger, an LED for a specific button, etc.</param> | ||
/// <param name="Name">An optional name for the output</param> | ||
/// <param name="CustomDataType">Valid (and required) only for outputs marked as <see cref="OutputAxisTrait.RawDataOnly"/></param> | ||
public readonly record struct OutputDescription(int Index, OutputAxisTrait Traits, int? AssociatedAxisIndex = null, string? Name = null, Type? CustomDataType = null); |
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.
AssociatedAxisIndex
should probably be AssociatedAxes
and be a nullable IReadOnlyList<int>
for consistency with the other structs. CustomDataType
I don't think should be included in the description, and we should instead make this inferable from the traits.
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.
should probably be [plural]
wouldnt that only apply to "OutputAxisGroup"s? this is more like TwinIndex
in AxisDescription
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.
Yes now that we have decided that axis groups are going to exist. These comments did not have knowledge of eachother seemingly 😅
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.
CustomDataType
I don't think should be included in the description, and we should instead make this inferable from the traits
I also don't like it, but it was just off-the-dome in the last few minutes. all in all im not sure how to handle the typing for this sort of thing in a graceful way atm
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.
Would recommend replacing with my other comment i.e. the try get info. Axis/output description needn't specify this as it is likely going to be a one to many relationship from axes/outputs to additional metadata available.
/// <param name="index">The index of the <see cref="OutputDescription"/> in <see cref="Outputs"/></param> | ||
/// <param name="values">A pointer to the value(s) to be set</param> | ||
public void SetOutput<T>(int index, T* values, int count = 1) where T : unmanaged => throw new NotImplementedException(); | ||
} |
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.
Come to think of it, we should probably add a TryGetAxisInfo<T>
and a TryGetOutputInfo<T>
so that we can have extensions in the future.
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.
this could be a nicer way to handle the typing - kind of enforces the idea that axis devices should strive to use similar output types where possible. I wonder how this would extend to the incoming "OutputGroup"
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.
that being said, i think that sort of api needs to be more thoroughly thought out than the next 30 minutes would allow us
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 think I'd be happy defining these two methods and just having no acceptable types for T atm i.e. Silk.NET reserves the right to add device-type-specific information to aid in axis identification, mapping, configuration, etc. Use of these APIs shouldn't be encouraged as the happy path, but it's sometimes useful to get more info than our intentionally over-generalised API provides.
LEDBrightness = 1 << 4 | LED, | ||
LEDRed = 1u << 5 | LED, | ||
LEDGreen = 1u << 6 | LED, | ||
LEDBlue = 1u << 7 | LED, | ||
LEDWhite = 1u << 8 | LED, |
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.
Kind of feels like we need output groups as well. Which I guess makes sense from a consistency standpoint.
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.
it does feel that way huh. could get rid of all these different sub-types of LED in favor of an LED OutputAxisGroupTypeNamePending
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.
Basically I think we should just have a very similar API surface for outputs as we do axes - we worked hard on making that generalised abstraction and I like the trait system that you came up with e.g. if it's an LED and it has 3 axes you can assume they're RGB etc
|
Summary of the PR
Adds the axis-based input proposal's first draft
Related issues, Discord discussions, or proposals
Several I've lost track of and I am sorry to report I am feeling particularly lazy after spewing so many words from my fingertips in a single afternoon
Further Comments
Any and all feedback ahead of our discussion this sunday is welcome - even if just for clarity of writing, and especially re: the contents of the proposal