Files
RetroArch/menu/menu_bind_trigger.h
T
LibretroAdmin 39f64dd580 menu: pulling a trigger binds its axis, not its button
Some triggers are a button and an axis at once: a DualSense's and a
DualShock 4's report a button as soon as the trigger leaves its rest,
and its position on an axis. Binding L2 or R2 by pressing it looked at
buttons first, so such a trigger was bound to its button: on or off,
with its analog position bound to nothing.

When a button answers while L2 or R2 is being bound, the trigger's
axis is now looked for and bound in the button's place. It is told by
two things together: it rests at an end of its range, which a stick
does not, and it has just left that rest, which the other trigger has
not (menu/menu_bind_trigger.h). The rest of that pull is not taken for
the next bind's press. A trigger that is a button alone is bound to
its button, as before, and so is every other control.

samples/input/bind_trigger_axis covers the choice of axis: the
trigger's first step, a full pull, a stick held over, noise at rest, a
trigger resting at the top, an axis resting in the middle. It runs in
CI. The capture itself was not run with a controller.
2026-10-05 01:37:38 +02:00

64 lines
2.4 KiB
C

/* RetroArch - A frontend for libretro.
*
* RetroArch is free software: you can redistribute it and/or modify it under the terms
* of the GNU General Public License as published by the Free Software Found-
* ation, either version 3 of the License, or (at your option) any later version.
*
* RetroArch is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY;
* without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
* PURPOSE. See the GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License along with RetroArch.
* If not, see <http://www.gnu.org/licenses/>.
*/
#ifndef MENU_BIND_TRIGGER_H__
#define MENU_BIND_TRIGGER_H__
#include <stdint.h>
#include <retro_inline.h>
#include "../input/input_defines.h"
/* Binding L2 or R2 by pressing it.
*
* Some triggers are a button and an axis at once: a DualSense's and a
* DualShock 4's report a button as soon as the trigger leaves its
* rest, and its position on an axis. The capture looks at buttons
* first, so such a trigger was bound to its button and was on or off
* from then on, with its analog position bound to nothing.
*
* When a button answers while L2 or R2 is being bound, the trigger's
* axis is looked for, and bound in the button's place if it is there.
* It is told by two things together: it rests at an end of its range,
* which a stick does not, and it has just left that rest, which the
* other trigger has not.
*
* Returns the bind for that axis, in the direction away from its rest,
* or AXIS_NONE when there is none - a trigger that is a button alone,
* which is then bound to the button as before. */
/* how near an end an axis has to rest to be a trigger's */
#define MENU_BIND_TRIGGER_REST 0x7000
/* and how far it has to have left it: more than noise, less than the
* first step a trigger reports - one 255th of the range is 257 */
#define MENU_BIND_TRIGGER_MOVED 128
static INLINE uint32_t menu_bind_trigger_axis(const int16_t *now,
const int16_t *rest, unsigned count)
{
unsigned a;
for (a = 0; a < count; a++)
{
int at_rest = rest[a];
int moved = (int)now[a] - at_rest;
if (at_rest <= -MENU_BIND_TRIGGER_REST && moved >= MENU_BIND_TRIGGER_MOVED)
return AXIS_POS(a);
if (at_rest >= MENU_BIND_TRIGGER_REST && moved <= -MENU_BIND_TRIGGER_MOVED)
return AXIS_NEG(a);
}
return AXIS_NONE;
}
#endif