-
-
Notifications
You must be signed in to change notification settings - Fork 104
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
Refactor joystick handling #1811
base: main
Are you sure you want to change the base?
Conversation
cbrauers
commented
Aug 4, 2024
- Modularize EnumerateDevices into smaller overridable chunks
- Fix some issues with button and axis sorting and enable it
- Fix some issues with button and axis sorting and enable it
Build for this pull request: |
Axes.Add(new JoystickDevice() { Name = axisName, Label = axisLabel, Type = DeviceType.AnalogInput, JoystickDeviceType = JoystickDeviceType.Axis}); | ||
Log.Instance.log($"Added {DIJoystick.Information.InstanceName} Aspect {aspect} + Offset: {offset} Usage: {usage} Axis: {name} Label: {axisLabel}.", LogSeverity.Debug); | ||
|
||
RegisterAxis(device); |
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 method has three sub-methods abstracted for more specific overrides in derived classes and to keep function length down - derived classes do not need to copy the full size of the method if all they want to change is a line or two.
var buttons = Buttons.ToArray().ToList(); | ||
buttons.Sort(SortByPositionInDefintion); | ||
return Buttons; | ||
return Buttons.OrderBy(button => GetIndexForJoystickDevice(button)).ToList(); |
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 addresses two nuisances (cf. issue #1808):
- The mix of member "Buttons" and local "buttons" led to the sorted list being completely ignored
- List.Sort() uses an unstable sorting algorithm, effectively applying an undefined permutation to buttons without a sorting index.
The Lambda could also be a function pointer, writing it this way mainly makes it more explicit that it is acting on individual buttons.
Axes.Sort(SortByPositionInDefintion); | ||
|
||
return Axes; | ||
return Axes.OrderBy(axis => GetIndexForJoystickDevice(axis)).ToList(); |
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.
Same as the buttons, with the added fun that the sort function was run on the member axes, not the local axes.
// -2 = definition not found / no inputs in definition | ||
// -1 = index not found | ||
// 0 or greater: valid index | ||
return Definition?.Inputs?.FindIndex(input => input.Name == key) ?? -2; |
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.
Documented some outputs and changed the return value in case of null pointers from a valid index to something the caller can distinguish.
Added virtual keyword because this is something that derived classes may want to override: the naming scheme of derived classes is often not based on DirectInput numbers, whereas input.Name is always based on the "Button " scheme.
} | ||
|
||
int SortByPositionInDefintion(JoystickDevice b1, JoystickDevice b2) | ||
public int GetIndexForJoystickDevice(JoystickDevice button) |
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.
Enumerable.OrderBy, unlike List.Sort, allows us to define what property to sort by. Therefore, the approach to integrate the index retrieval into the function is somewhat different.
// Ensure items in definition appear first | ||
if(index < 0) | ||
{ | ||
index = Int32.MaxValue; // force undefined stuff to the end of the list |
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 inputs most relevant to MobiFlight users are probably spelled out in the definition. Entries not in the definition are likely to be less relevant, so let us move them after the named ones.
LogInputAdded(device, name); | ||
} | ||
|
||
protected void LogInputAdded(DeviceObjectInstance device, string label) |
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.
Trading debug information (calling function name) for DRYness here. If having the log point to dedicated logging methods is unwanted, I have a different compromise in mind as an alternative option (generate the string in a method and call Log.Instance.log with that).