Add RapidFire module
This commit is contained in:
parent
aa327e4557
commit
d5dfbf456f
43
docs/rapidfire.md
Normal file
43
docs/rapidfire.md
Normal file
@ -0,0 +1,43 @@
|
||||
# RapidFire
|
||||
|
||||
The RapidFire module lets a user send repeated key presses while a key is held.
|
||||
|
||||
Some instances where this may be useful are:
|
||||
|
||||
- MMOs and other games where you are encouraged to repeatedly spam a key
|
||||
- More responsive volume up and volume down
|
||||
- Faster cursor key navigation
|
||||
- Anywhere else you may need an ergonomic alternative to repetitive key tapping
|
||||
|
||||
## Keycodes
|
||||
|
||||
| Key | Description |
|
||||
| :------ | :--------------------------------------------------- |
|
||||
| `KC.RF` | Repeatedly sends the specified keycode while pressed |
|
||||
|
||||
## Usage
|
||||
|
||||
Each repeat counts as one full cycle of pressing and releasing. RapidFire works with chording (i.e., holding Shift plus a RapidFire key will repeatedly send the shifted version of that RapidFire key) and chaining (i.e., `KC.RF(KC.LSHIFT(KC.A))`. Multiple RapidFire keys can be held down at the same time, and their timers work independently of each other.
|
||||
|
||||
The RapidFire keycode has a few different options:
|
||||
|
||||
| Option | Default Value | Description |
|
||||
| :-------------------: | :-----------: | :----------------------------------------------------------------------------------------------------------------------------------------------------------- |
|
||||
| `repeat` | `100` | The delay between repeats. Note: `2` appears to be the minimum effective value. If you run into issues, try increasing this value. |
|
||||
| `wait` | `200` | The delay before starting to repeat. Useful if you want to be able to type with keys that have a low `repeat` value. |
|
||||
| `randomize_repeat` | `False` | Randomize the value of `repeat`. Useful for making the repetitive input look human in instances where you may be flagged as a bot otherwise. |
|
||||
| `randomize_magnitude` | `15` | The magnitude of the randomization. If randomization is enabled, the repeat delay will be `repeat` plus or minus a random value up to this amount. |
|
||||
|
||||
### Example Code
|
||||
|
||||
```python
|
||||
from kmk.modules.rapidfire import RapidFire
|
||||
|
||||
keyboard.modules.append(RapidFire())
|
||||
|
||||
# After 200 milliseconds, repeatedly send Shift+A every 75-125 milliseconds while the RapidFire key is held
|
||||
keyboard.keymap = [[
|
||||
KC.RF(KC.LSFT(KC.A), wait=200, repeat=100, randomize_repeat=True, randomize_magnitude=25)
|
||||
]]
|
||||
|
||||
```
|
82
kmk/modules/rapidfire.py
Normal file
82
kmk/modules/rapidfire.py
Normal file
@ -0,0 +1,82 @@
|
||||
from kmk.keys import make_argumented_key
|
||||
from kmk.modules import Module
|
||||
from random import randint
|
||||
|
||||
|
||||
class RapidFireMeta:
|
||||
def __init__(
|
||||
self,
|
||||
kc,
|
||||
repeat=100,
|
||||
wait=200,
|
||||
randomize_repeat=False,
|
||||
randomize_magnitude=15,
|
||||
):
|
||||
self.kc = kc
|
||||
self.repeat = repeat
|
||||
self.wait = wait
|
||||
self.randomize_repeat = randomize_repeat
|
||||
self.randomize_magnitude = randomize_magnitude
|
||||
|
||||
|
||||
class RapidFire(Module):
|
||||
_active_keys = {}
|
||||
|
||||
def __init__(self):
|
||||
make_argumented_key(
|
||||
validator=RapidFireMeta,
|
||||
names=("RF",),
|
||||
on_press=self._rf_pressed,
|
||||
on_release=self._rf_released,
|
||||
)
|
||||
|
||||
def _get_repeat(self, key):
|
||||
if key.meta.randomize_repeat:
|
||||
return key.meta.repeat + randint(
|
||||
-key.meta.randomize_magnitude, key.meta.randomize_magnitude
|
||||
)
|
||||
return key.meta.repeat
|
||||
|
||||
def _on_repeat_timeout(self, key, keyboard):
|
||||
keyboard.tap_key(key.meta.kc)
|
||||
repeat_timeout_key = keyboard.set_timeout(
|
||||
self._get_repeat(key),
|
||||
lambda: self._on_repeat_timeout(key, keyboard),
|
||||
)
|
||||
self._active_keys[key] = repeat_timeout_key
|
||||
|
||||
def _on_wait_timeout(self, key, keyboard):
|
||||
self._on_repeat_timeout(key, keyboard)
|
||||
|
||||
def _rf_pressed(self, key, keyboard, *args, **kwargs):
|
||||
keyboard.tap_key(key.meta.kc)
|
||||
wait_timeout_key = keyboard.set_timeout(
|
||||
key.meta.wait, lambda: self._on_wait_timeout(key, keyboard)
|
||||
)
|
||||
self._active_keys[key] = wait_timeout_key
|
||||
|
||||
def _rf_released(self, key, keyboard, *args, **kwargs):
|
||||
if key in self._active_keys:
|
||||
keyboard.cancel_timeout(self._active_keys[key])
|
||||
self._active_keys.pop(key)
|
||||
|
||||
def during_bootup(self, keyboard):
|
||||
return
|
||||
|
||||
def before_matrix_scan(self, keyboard):
|
||||
return
|
||||
|
||||
def before_hid_send(self, keyboard):
|
||||
return
|
||||
|
||||
def after_hid_send(self, keyboard):
|
||||
return
|
||||
|
||||
def on_powersave_enable(self, keyboard):
|
||||
return
|
||||
|
||||
def on_powersave_disable(self, keyboard):
|
||||
return
|
||||
|
||||
def after_matrix_scan(self, keyboard):
|
||||
return
|
Loading…
Reference in New Issue
Block a user