Commit Graph
24 Commits
Author SHA1 Message Date
Stuart Carnie 82c34fd550 chore: Improve Swift ergonomics 2020-01-26 10:27:47 -07:00
Daniele Cattaneo b632e05be9 Enlarge the minimum range of values required to enable auto-calibration. 2020-01-01 03:01:10 +01:00
Daniele Cattaneo 8ca6a436eb Fix handling of center value to restore behavior originally introduced in commit fbb49c7. Do not regress wrt commit 367241c by enabling/disabling auto-calibration independently on each axis direction. 2019-12-31 17:34:10 +01:00
Daniele Cattaneo 1591205112 Allow disabling auto-calibration from the device database. 2019-12-15 00:43:11 +01:00
Daniele Cattaneo 5812663036 Minor cleanup and removal of duplicated code. 2019-12-14 23:28:02 +01:00
Daniele Cattaneo ae7ded2f2e Move the rest of the axis calibration logic from OEHIDEvent to OEDeviceHandler 2019-12-14 23:09:36 +01:00
Daniele Cattaneo 367241c7b7 Enable auto-calibration only when the range of inputs seen is larger than the deadzone.
Fixes controllers that exhibit some jitter when the sticks are resting (for example the PS4 controller)
2019-12-14 18:42:35 +01:00
Daniele Cattaneo 38974f7ad7 Expose methods to allow modification of the current state of the auto-calibration system. 2019-12-13 22:45:52 +01:00
clobber 95a72bac60 Merge pull request #25 from piki/piki/auto-calibrate
Automatically calibrate analog axes
2019-12-09 23:58:10 -06:00
clobber ec66a54171 Fix issue #2326. fix the issues introduced in the previous fix for this issue. Now known controllers should work like before. 2019-12-03 19:44:45 -08:00
Patrick Reynolds fbb49c7a04 Learn only extremes, not the middle
Callers (i.e., OEHIDEvent) now pass an expected middle value to the
scaledValue function, so scaledValue doesn't have to learn the middle.  We
assume the middle is in fact the middle of the IOKit range for the HID
class.

This fixes the drift problem where the character would sometimes walk
slowly if the user had only fully trained the calibration in one direction
on an axis.

The only remaining limitation at this point is: you must run before you
can walk.  If you only ever push the joystick to 25%, the scaler will
assume 25% is the max and will scale it to +1.0 instead of +0.25.  I think
it's rare users will even notice (most games push the analog stick to its
extremes most of the time), and if they do, pushing the stick to its
extreme just once solves the problem.
2019-10-11 02:37:41 -04:00
Patrick Reynolds 356aa8d89b Refuse to scale until 8 samples have been learned
This commit fixes the "relearn" problem from 65fcd7af27.  We now won't
scale a positive value unless a (potentially non-continuous) subsequence
of 8 monotonically increasing values have been observed, and we won't
scale a negative value unless 8 decreasing values have been observed.
While we're waiting for those 8 samples, we simply use the default scaler
that assumes the device returns the full range of values expected by
IOKit.

To put it simply, we will use the default scalar for each direction of
each axis until we have 8 good samples about that direction of that axis.

This learning algorithm can still get confused about the center.  If you
push an axis to the top of its range (100%) but only halfway to the bottom
(25%), then the learned middle will be 62.5% instead of 50%, so 50% will
actually map to a slightly negative value outside the dead zone.  (Link
walks slowly to the left...)  The problem is self correcting as soon as
the user pushes the stick to both ends of the range.

There's still room to improve that.  Instead of learning the middle, we
can assume that each device's actual middle is somewhere near the IOKit
expected middle.  We really only need to learn min and max.
2019-10-11 02:17:56 -04:00
Patrick Reynolds 65fcd7af27 Automatically learn analog-control calibration
The default OEHIDEvent class assumes that controller devices will always
use the full range specified by IOKit.  For example, if IOKit maps a
control to the range 0..255, OEHIDEvent assumes that every attached device
will return 0 and 255 when pushed to its physical limits.

Many N64 controller adapters apparently do not behave this way.  They
return less than the full range of values IOKit expects, leading to
characters and vehicles being unable to use their full range of motion.
Link can only tiptoe in Zelda games, for example.

This patch teaches the OEDeviceHandler class to automatically learn the
bounds of each analog axis, individually.  So if the actual physical range
of the X axis of an N64 controller is 49..192, all logical values will be
scaled based on that range instead of 0..255.

This, I think, is tidier than adding a calibration interface.  Why ask the
user to configure what the software can learn for itself?

One limitation is that OEDeviceHandler must relearn its range each time
you start the the emulator.  That means until you've pushed the joystick
through its full range of motion, the scaling will behave in unexpected
ways.  For example, if you push an X axis to the right, the learned range
might be 128..192.  That rightward push will correctly be scaled to +1.0,
but when you return the stick to the center, 128 will now scale to -1.0.
Pushing the stick to the left fixes this by teaching the program that the
minimum is (e.g.) 49 and not 128.  Put simply, the user must push all
analog axes through their full range of motion at least once when the
emulator starts.

There's room for improvement on this "relearn" issue, which I'll address
in a follow-up commit.
2019-10-11 01:14:39 -04:00
Daniele Cattaneo f7b4c7dfed Add a way to override the default scaling for axis events 2019-08-30 23:41:02 +02:00
clobber 835ac771f6 Keep track of the Function (Fn) key state and also allow it to be bound.
This can be used for computer system plugins as a way to ignore system media key presses, so that F1-F12 keys may only register if Fn is pressed. The downside is this does not respect OS keyboard preferences if a user has changed the default settings, but seems to be the best we can do without relying on CGEventTap to track events which will require accessibility access. Attempted app-side workarounds by overriding sendEvent: or checking NSApp.currentEvent to block NSSystemDefined type NSEvent's proved to be useless due to syncing.
2018-10-07 17:44:06 -05:00
clobber 46815b19bf Lower the default dead zone percentage.
Modern gamepad analogs are very sensitive with minimal dead zone. This may be a better medium between modern (MFi/PS3/PS4/Xbox/8bitdo/Steam) and legacy (Logitech era) devices. 4096/32768 = 0.125
2017-02-19 19:00:13 -06:00
clobber 2118039958 Remove silly warning. 2016-10-09 17:29:08 -07:00
clobber 431195e021 Annotate binding and device classes. 2015-11-29 14:05:18 -08:00
clobber 379ee66b5a Fix issue with plugging/unplugging controllers while a game is running.
There are two issues in this case:
1. XPC messages are processed in a private queue making OEDeviceManager calls unsafe when retrieving device handlers. We solve this problem by making thread safe operations.
2. Sometimes we may receive binding updates on the emulator process before the process has had the time to recognize a device that is connected. This is solved by using placeholder device objects that we replace with real devices in OEHIDEvent when the device is finally parsed. This is possible because if a device is added to the UI process it will be added to the emulator process eventually.
2015-11-29 02:15:22 -08:00
clobber 3836c5bf82 Add a unique identifier to OEDeviceHandler. This allows multiple processes to uniquely identify a device across processes, later on OEDeviceHandler will be sent over XPC so we can move event handling in the emulator process instead. 2015-11-28 16:28:28 -08:00
Christoph Leimbrock 591375ed48 Remove comments from .strings files 2015-02-28 22:09:57 +01:00
clobber 73ea2c9eed Rename OEDeviceHandler name to product. 2014-03-01 23:09:17 -08:00
clobber 843b91d566 Also use device name to get device descriptions. 2014-03-01 17:30:43 -08:00
Remy Demarest a0434761d7 Move OpenEmuSystem and OpenEmuBase frameworks into their own project. 2013-04-07 00:21:09 -07:00