init commit
This commit is contained in:
@@ -0,0 +1,29 @@
|
||||
# Gamepad
|
||||
|
||||
Some predefined gamepad bindings for doing tasks like clicking, scrolling and moving your cursor.
|
||||
|
||||
### Usage
|
||||
|
||||
To enable the gamepad bindings activate tag `user.gamepad` in [gamepad_settings.talon](./gamepad_settings.talon)
|
||||
|
||||
## Demo - Using gamepad
|
||||
|
||||
[YouTube - Gamepad demo](https://youtu.be/zNeiZ9nnK_A)
|
||||
|
||||
## Gamepad tester
|
||||
|
||||

|
||||
|
||||
### Usage
|
||||
|
||||
1. Say `"gamepad tester"` to open gamepad tester UI.
|
||||
1. Press buttons on actual gamepad and see interaction in UI.
|
||||
1. Close gamepad tester by saying `"gamepad tester"` again.
|
||||
|
||||
### Demo - Gamepad tester
|
||||
|
||||
[YouTube - Gamepad tester demo](https://youtu.be/FzfIlaHm8_w)
|
||||
|
||||
### Conflict with existing gamepad implementations
|
||||
|
||||
The gamepad tester doesn't disable your existing gamepad implementations. If you don't want your existing gamepad implementations to trigger during the testing phase you can add `not tag: user.gamepad_tester` at the top of your gamepad Talon files.
|
||||
@@ -0,0 +1,304 @@
|
||||
from talon import Module, actions, ctrl, ui
|
||||
from talon.screen import Screen
|
||||
|
||||
screen: Screen = ui.main_screen()
|
||||
slow_scroll = False
|
||||
slow_mouse_move = False
|
||||
|
||||
mod = Module()
|
||||
mod.tag("gamepad", desc="Activate tag to enable gamepad bindings")
|
||||
|
||||
|
||||
@mod.action_class
|
||||
class Actions:
|
||||
# DPAD buttons
|
||||
|
||||
def gamepad_press_dpad_left():
|
||||
"""Gamepad press button dpad left"""
|
||||
gamepad_mouse_jump("left")
|
||||
|
||||
def gamepad_release_dpad_left():
|
||||
"""Gamepad release button dpad left"""
|
||||
actions.skip()
|
||||
|
||||
def gamepad_press_dpad_up():
|
||||
"""Gamepad press button dpad up"""
|
||||
gamepad_mouse_jump("up")
|
||||
|
||||
def gamepad_release_dpad_up():
|
||||
"""Gamepad release button dpad up"""
|
||||
actions.skip()
|
||||
|
||||
def gamepad_press_dpad_right():
|
||||
"""Gamepad press button dpad right"""
|
||||
gamepad_mouse_jump("right")
|
||||
|
||||
def gamepad_release_dpad_right():
|
||||
"""Gamepad release button dpad right"""
|
||||
actions.skip()
|
||||
|
||||
def gamepad_press_dpad_down():
|
||||
"""Gamepad press button dpad down"""
|
||||
gamepad_mouse_jump("down")
|
||||
|
||||
def gamepad_release_dpad_down():
|
||||
"""Gamepad release button dpad down"""
|
||||
actions.skip()
|
||||
|
||||
# Compass / ABXY buttons
|
||||
|
||||
def gamepad_press_west():
|
||||
"""Gamepad press button west"""
|
||||
actions.mouse_drag(0)
|
||||
|
||||
def gamepad_release_west():
|
||||
"""Gamepad release button west"""
|
||||
actions.mouse_release(0)
|
||||
|
||||
def gamepad_press_north():
|
||||
"""Gamepad press button north"""
|
||||
actions.mouse_drag(1)
|
||||
|
||||
def gamepad_release_north():
|
||||
"""Gamepad release button north"""
|
||||
actions.mouse_release(1)
|
||||
|
||||
def gamepad_press_east():
|
||||
"""Gamepad press button east"""
|
||||
actions.key("ctrl:down")
|
||||
actions.mouse_click()
|
||||
actions.key("ctrl:up")
|
||||
|
||||
def gamepad_release_east():
|
||||
"""Gamepad release button east"""
|
||||
actions.skip()
|
||||
|
||||
def gamepad_press_south():
|
||||
"""Gamepad press button south"""
|
||||
actions.mouse_drag(2)
|
||||
|
||||
def gamepad_release_south():
|
||||
"""Gamepad release button south"""
|
||||
actions.mouse_release(2)
|
||||
|
||||
# Select / Start buttons
|
||||
|
||||
def gamepad_press_select():
|
||||
"""Gamepad press button select"""
|
||||
actions.skip()
|
||||
|
||||
def gamepad_release_select():
|
||||
"""Gamepad release button select"""
|
||||
actions.skip()
|
||||
|
||||
def gamepad_press_start():
|
||||
"""Gamepad press button start"""
|
||||
actions.speech.toggle()
|
||||
|
||||
def gamepad_release_start():
|
||||
"""Gamepad release button start"""
|
||||
actions.skip()
|
||||
|
||||
# Shoulder buttons
|
||||
|
||||
def gamepad_press_left_shoulder():
|
||||
"""Gamepad press button left shoulder"""
|
||||
actions.user.go_back()
|
||||
|
||||
def gamepad_release_left_shoulder():
|
||||
"""Gamepad release button left shoulder"""
|
||||
actions.skip()
|
||||
|
||||
def gamepad_press_right_shoulder():
|
||||
"""Gamepad press button right shoulder"""
|
||||
actions.user.go_forward()
|
||||
|
||||
def gamepad_release_right_shoulder():
|
||||
"""Gamepad release button right shoulder"""
|
||||
actions.skip()
|
||||
|
||||
# Stick buttons
|
||||
|
||||
def gamepad_press_left_stick():
|
||||
"""Gamepad press button left thumb stick"""
|
||||
gamepad_scroll_slow_toggle()
|
||||
|
||||
def gamepad_release_left_stick():
|
||||
"""Gamepad release button left thumb stick"""
|
||||
actions.skip()
|
||||
|
||||
def gamepad_press_right_stick():
|
||||
"""Gamepad press button right thumb stick"""
|
||||
gamepad_mouse_move_slow_toggle()
|
||||
|
||||
def gamepad_release_right_stick():
|
||||
"""Gamepad release button right thumb stick"""
|
||||
actions.skip()
|
||||
|
||||
# Analog triggers
|
||||
|
||||
def gamepad_trigger_left(value: float):
|
||||
"""Gamepad trigger left movement"""
|
||||
gamepad_scroll(0, value * -1)
|
||||
|
||||
def gamepad_trigger_right(value: float):
|
||||
"""Gamepad trigger right movement"""
|
||||
gamepad_scroll(0, value)
|
||||
|
||||
# Analog thumb sticks
|
||||
|
||||
def gamepad_stick_left(x: float, y: float):
|
||||
"""Gamepad left stick movement"""
|
||||
gamepad_scroll(x, y)
|
||||
|
||||
def gamepad_stick_right(x: float, y: float):
|
||||
"""Gamepad right stick movement"""
|
||||
gamepad_mouse_move(x, y)
|
||||
|
||||
# Scaffolding actions used by the Talon file
|
||||
|
||||
def gamepad_button_down(button: str):
|
||||
"""Gamepad press button <button>"""
|
||||
match button:
|
||||
# DPAD buttons
|
||||
case "dpad_left":
|
||||
actions.user.gamepad_press_dpad_left()
|
||||
case "dpad_up":
|
||||
actions.user.gamepad_press_dpad_up()
|
||||
case "dpad_right":
|
||||
actions.user.gamepad_press_dpad_right()
|
||||
case "dpad_down":
|
||||
actions.user.gamepad_press_dpad_down()
|
||||
|
||||
# Compass / ABXY buttons
|
||||
case "west":
|
||||
actions.user.gamepad_press_west()
|
||||
case "north":
|
||||
actions.user.gamepad_press_north()
|
||||
case "east":
|
||||
actions.user.gamepad_press_east()
|
||||
case "south":
|
||||
actions.user.gamepad_press_south()
|
||||
|
||||
# Select / Start buttons
|
||||
case "select":
|
||||
actions.user.gamepad_press_select()
|
||||
case "start":
|
||||
actions.user.gamepad_press_start()
|
||||
|
||||
# Shoulder buttons
|
||||
case "left_shoulder":
|
||||
actions.user.gamepad_press_left_shoulder()
|
||||
case "right_shoulder":
|
||||
actions.user.gamepad_press_right_shoulder()
|
||||
|
||||
# Stick buttons
|
||||
case "left_stick":
|
||||
actions.user.gamepad_press_left_stick()
|
||||
case "right_stick":
|
||||
actions.user.gamepad_press_right_stick()
|
||||
|
||||
case _:
|
||||
raise ValueError(f"Unknown button: {button}")
|
||||
|
||||
def gamepad_button_up(button: str):
|
||||
"""Gamepad release button <button>"""
|
||||
match button:
|
||||
# DPAD buttons
|
||||
case "dpad_left":
|
||||
actions.user.gamepad_release_dpad_left()
|
||||
case "dpad_up":
|
||||
actions.user.gamepad_release_dpad_up()
|
||||
case "dpad_right":
|
||||
actions.user.gamepad_release_dpad_right()
|
||||
case "dpad_down":
|
||||
actions.user.gamepad_release_dpad_down()
|
||||
|
||||
# Compass / ABXY buttons
|
||||
case "west":
|
||||
actions.user.gamepad_release_west()
|
||||
case "north":
|
||||
actions.user.gamepad_release_north()
|
||||
case "east":
|
||||
actions.user.gamepad_release_east()
|
||||
case "south":
|
||||
actions.user.gamepad_release_south()
|
||||
|
||||
# Select / Start buttons
|
||||
case "select":
|
||||
actions.user.gamepad_release_select()
|
||||
case "start":
|
||||
actions.user.gamepad_release_start()
|
||||
|
||||
# Shoulder buttons
|
||||
case "left_shoulder":
|
||||
actions.user.gamepad_release_left_shoulder()
|
||||
case "right_shoulder":
|
||||
actions.user.gamepad_release_right_shoulder()
|
||||
|
||||
# Stick buttons
|
||||
case "left_stick":
|
||||
actions.user.gamepad_release_left_stick()
|
||||
case "right_stick":
|
||||
actions.user.gamepad_release_right_stick()
|
||||
|
||||
case _:
|
||||
raise ValueError(f"Unknown button: {button}")
|
||||
|
||||
|
||||
def gamepad_scroll(x: float, y: float):
|
||||
"""Perform gamepad scrolling"""
|
||||
multiplier = 1.5 if slow_scroll else 3
|
||||
x = x**3 * multiplier
|
||||
y = y**3 * multiplier
|
||||
|
||||
if x != 0 or y != 0:
|
||||
actions.mouse_scroll(x=x, y=y, by_lines=True)
|
||||
|
||||
|
||||
def gamepad_mouse_move(dx: float, dy: float):
|
||||
"""Perform gamepad mouse cursor movement"""
|
||||
multiplier = 0.1 if slow_mouse_move else 0.2
|
||||
x, y = ctrl.mouse_pos()
|
||||
screen = get_screen(x, y)
|
||||
dx = dx**3 * screen.dpi * multiplier
|
||||
dy = dy**3 * screen.dpi * multiplier
|
||||
actions.mouse_move(x + dx, y + dy)
|
||||
|
||||
|
||||
def gamepad_scroll_slow_toggle():
|
||||
"""Toggle gamepad slow scroll mode"""
|
||||
global slow_scroll
|
||||
slow_scroll = not slow_scroll
|
||||
|
||||
|
||||
def gamepad_mouse_move_slow_toggle():
|
||||
"""Toggle gamepad slow mouse move mode"""
|
||||
global slow_mouse_move
|
||||
slow_mouse_move = not slow_mouse_move
|
||||
|
||||
|
||||
def gamepad_mouse_jump(direction: str):
|
||||
"""Move the mouse cursor to the specified quadrant of the active screen"""
|
||||
x, y = ctrl.mouse_pos()
|
||||
rect = ui.screen_containing(x, y).rect
|
||||
|
||||
# Half distance between cursor and screen edge
|
||||
match direction:
|
||||
case "up":
|
||||
y = rect.top + (y - rect.top) / 2
|
||||
case "down":
|
||||
y = rect.bot - (rect.bot - y) / 2
|
||||
case "left":
|
||||
x = rect.left + (x - rect.left) / 2
|
||||
case "right":
|
||||
x = rect.right - (rect.right - x) / 2
|
||||
|
||||
actions.mouse_move(x, y)
|
||||
|
||||
|
||||
def get_screen(x: float, y: float) -> Screen:
|
||||
global screen
|
||||
if not screen.contains(x, y):
|
||||
screen = ui.screen_containing(x, y)
|
||||
return screen
|
||||
@@ -0,0 +1,49 @@
|
||||
tag: user.gamepad
|
||||
and not tag: user.gamepad_tester
|
||||
-
|
||||
|
||||
# DPAD buttons
|
||||
gamepad(dpad_left:down): user.gamepad_button_down("dpad_left")
|
||||
gamepad(dpad_left:up): user.gamepad_button_up("dpad_left")
|
||||
gamepad(dpad_up:down): user.gamepad_button_down("dpad_up")
|
||||
gamepad(dpad_up:up): user.gamepad_button_up("dpad_up")
|
||||
gamepad(dpad_right:down): user.gamepad_button_down("dpad_right")
|
||||
gamepad(dpad_right:up): user.gamepad_button_up("dpad_right")
|
||||
gamepad(dpad_down:down): user.gamepad_button_down("dpad_down")
|
||||
gamepad(dpad_down:up): user.gamepad_button_up("dpad_down")
|
||||
|
||||
# Compass / ABXY buttons
|
||||
gamepad(west:down): user.gamepad_button_down("west")
|
||||
gamepad(west:up): user.gamepad_button_up("west")
|
||||
gamepad(north:down): user.gamepad_button_down("north")
|
||||
gamepad(north:up): user.gamepad_button_up("north")
|
||||
gamepad(east:down): user.gamepad_button_down("east")
|
||||
gamepad(east:up): user.gamepad_button_up("east")
|
||||
gamepad(south:down): user.gamepad_button_down("south")
|
||||
gamepad(south:up): user.gamepad_button_up("south")
|
||||
|
||||
# Select / Start buttons
|
||||
gamepad(select:down): user.gamepad_button_down("select")
|
||||
gamepad(select:up): user.gamepad_button_up("select")
|
||||
gamepad(start:down): user.gamepad_button_down("start")
|
||||
gamepad(start:up): user.gamepad_button_up("start")
|
||||
|
||||
# Shoulder buttons
|
||||
gamepad(l1:down): user.gamepad_button_down("left_shoulder")
|
||||
gamepad(l1:up): user.gamepad_button_up("left_shoulder")
|
||||
gamepad(r1:down): user.gamepad_button_down("right_shoulder")
|
||||
gamepad(r1:up): user.gamepad_button_up("right_shoulder")
|
||||
|
||||
# Stick buttons
|
||||
gamepad(l3:down): user.gamepad_button_down("left_stick")
|
||||
gamepad(l3:up): user.gamepad_button_up("left_stick")
|
||||
gamepad(r3:down): user.gamepad_button_down("right_stick")
|
||||
gamepad(r3:up): user.gamepad_button_up("right_stick")
|
||||
|
||||
# Analog triggers
|
||||
gamepad(l2:repeat): user.gamepad_trigger_left(value)
|
||||
gamepad(r2:repeat): user.gamepad_trigger_right(value)
|
||||
|
||||
# Analog thumb sticks
|
||||
gamepad(left_xy:repeat): user.gamepad_stick_left(x, y*-1)
|
||||
gamepad(right_xy:repeat): user.gamepad_stick_right(x, y*-1)
|
||||
@@ -0,0 +1,2 @@
|
||||
# Uncomment to enable gamepad support
|
||||
# tag(): user.gamepad
|
||||
Binary file not shown.
|
After Width: | Height: | Size: 26 KiB |
@@ -0,0 +1,290 @@
|
||||
from talon import Context, Module, ui
|
||||
from talon.canvas import Canvas, MouseEvent
|
||||
from talon.screen import Screen
|
||||
from talon.skia.canvas import Canvas as SkiaCanvas
|
||||
from talon.types import Point2d, Rect
|
||||
|
||||
mod = Module()
|
||||
ctx = Context()
|
||||
canvas: Canvas | None = None
|
||||
last_mouse_pos: Point2d | None = None
|
||||
|
||||
mod.tag("gamepad_tester", "Gamepad tester gui is showing")
|
||||
|
||||
buttons = {
|
||||
"dpad_up": False,
|
||||
"dpad_right": False,
|
||||
"dpad_down": False,
|
||||
"dpad_left": False,
|
||||
"north": False,
|
||||
"east": False,
|
||||
"south": False,
|
||||
"west": False,
|
||||
"select": False,
|
||||
"start": False,
|
||||
"l1": False,
|
||||
"r1": False,
|
||||
"l3": False,
|
||||
"r3": False,
|
||||
}
|
||||
|
||||
triggers = {
|
||||
"l2": 0.0,
|
||||
"r2": 0.0,
|
||||
}
|
||||
|
||||
sticks = {
|
||||
"left": (0.0, 0.0),
|
||||
"right": (0.0, 0.0),
|
||||
}
|
||||
|
||||
BACKGROUND_COLOR = "fffafa" # Snow
|
||||
BORDER_COLOR = "000000" # Black
|
||||
FONT_SIZE = 16
|
||||
WIDTH = 900
|
||||
HEIGHT = 800
|
||||
CIRCLE_RADIUS = 100
|
||||
BUTTON_OFFSET = CIRCLE_RADIUS / 2
|
||||
BUTTON_RADIUS = BUTTON_OFFSET / 2
|
||||
ROW_OFFSET = CIRCLE_RADIUS * 1.25
|
||||
BUTTON_FLAT_WIDTH = BUTTON_RADIUS * 3
|
||||
BUTTON_FLAT_HEIGHT = BUTTON_RADIUS
|
||||
TRIGGER_HEIGHT = CIRCLE_RADIUS
|
||||
BUTTON_OFFSETS = [(0, -1), (1, 0), (0, 1), (-1, 0)]
|
||||
|
||||
|
||||
def render_round_button(c: SkiaCanvas, x: float, y: float, is_pressed: bool):
|
||||
c.paint.style = c.paint.Style.FILL if is_pressed else c.paint.Style.STROKE
|
||||
c.draw_circle(x, y, BUTTON_RADIUS)
|
||||
|
||||
|
||||
def render_square_button(c: SkiaCanvas, x: float, y: float, is_pressed: bool):
|
||||
c.paint.style = c.paint.Style.FILL if is_pressed else c.paint.Style.STROKE
|
||||
c.draw_rect(
|
||||
Rect(
|
||||
x - BUTTON_RADIUS,
|
||||
y - BUTTON_RADIUS,
|
||||
BUTTON_RADIUS * 2,
|
||||
BUTTON_RADIUS * 2,
|
||||
)
|
||||
)
|
||||
|
||||
|
||||
def render_flat_button(c: SkiaCanvas, x: float, y: float, is_pressed: bool):
|
||||
c.paint.style = c.paint.Style.FILL if is_pressed else c.paint.Style.STROKE
|
||||
c.draw_rect(
|
||||
Rect(
|
||||
x - BUTTON_FLAT_WIDTH / 2,
|
||||
y - BUTTON_FLAT_HEIGHT / 2,
|
||||
BUTTON_FLAT_WIDTH,
|
||||
BUTTON_FLAT_HEIGHT,
|
||||
)
|
||||
)
|
||||
|
||||
|
||||
def render_buttons(
|
||||
c: SkiaCanvas, x: float, y: float, useCircle: bool, buttons_ids: list[str]
|
||||
):
|
||||
c.paint.style = c.paint.Style.STROKE
|
||||
c.draw_circle(x, y, CIRCLE_RADIUS)
|
||||
for i, button_id in enumerate(buttons_ids):
|
||||
(offset_x, offset_y) = BUTTON_OFFSETS[i]
|
||||
button_x = x + offset_x * BUTTON_OFFSET
|
||||
button_y = y + offset_y * BUTTON_OFFSET
|
||||
is_pressed = buttons[button_id]
|
||||
if useCircle:
|
||||
render_round_button(c, button_x, button_y, is_pressed)
|
||||
else:
|
||||
render_square_button(c, button_x, button_y, is_pressed)
|
||||
|
||||
|
||||
def render_trigger(c: SkiaCanvas, x: float, y: float, value: float):
|
||||
# Render button outline
|
||||
c.paint.style = c.paint.Style.STROKE
|
||||
c.draw_rect(
|
||||
Rect(
|
||||
x - BUTTON_FLAT_WIDTH / 2,
|
||||
y - TRIGGER_HEIGHT,
|
||||
BUTTON_FLAT_WIDTH,
|
||||
TRIGGER_HEIGHT,
|
||||
)
|
||||
)
|
||||
# Render button value
|
||||
c.paint.style = c.paint.Style.FILL
|
||||
height = value * TRIGGER_HEIGHT
|
||||
c.draw_rect(
|
||||
Rect(
|
||||
x - BUTTON_FLAT_WIDTH / 2,
|
||||
y - height,
|
||||
BUTTON_FLAT_WIDTH,
|
||||
height,
|
||||
)
|
||||
)
|
||||
# Render value text
|
||||
text = str(round(value * 100))
|
||||
text_rect = c.paint.measure_text(text)[1]
|
||||
c.draw_text(
|
||||
text,
|
||||
x - text_rect.x - text_rect.width / 2,
|
||||
y - TRIGGER_HEIGHT - text_rect.height,
|
||||
)
|
||||
|
||||
|
||||
def render_stick(
|
||||
c: SkiaCanvas, x: float, y: float, is_pressed: bool, value_x: float, value_y: float
|
||||
):
|
||||
# Stick click
|
||||
if is_pressed:
|
||||
c.paint.style = c.paint.Style.FILL
|
||||
c.draw_circle(x, y, CIRCLE_RADIUS)
|
||||
return
|
||||
|
||||
c.paint.style = c.paint.Style.STROKE
|
||||
# Draw outer circle
|
||||
c.draw_circle(x, y, CIRCLE_RADIUS)
|
||||
# Draw cross
|
||||
c.draw_line(x - CIRCLE_RADIUS, y, x + CIRCLE_RADIUS, y)
|
||||
c.draw_line(x, y - CIRCLE_RADIUS, x, y + CIRCLE_RADIUS)
|
||||
dot_x = x + value_x * CIRCLE_RADIUS
|
||||
dot_y = y + value_y * CIRCLE_RADIUS
|
||||
# Draw line to dot
|
||||
c.draw_line(x, y, dot_x, dot_y)
|
||||
# Draw center dot
|
||||
c.paint.style = c.paint.Style.FILL
|
||||
c.draw_circle(dot_x, dot_y, 5)
|
||||
# Render value texts
|
||||
text = f"{round(value_x * 100)}, {round(value_y * 100)}"
|
||||
text_rect = c.paint.measure_text(text)[1]
|
||||
c.draw_text(
|
||||
text,
|
||||
x - text_rect.x - text_rect.width / 2,
|
||||
y - CIRCLE_RADIUS - text_rect.height,
|
||||
)
|
||||
|
||||
|
||||
def render_close_text(c: SkiaCanvas, x: float, y: float):
|
||||
text = 'Say "gamepad tester" to close'
|
||||
text_rect = c.paint.measure_text(text)[1]
|
||||
c.draw_text(
|
||||
text,
|
||||
x - text_rect.x - text_rect.width / 2,
|
||||
y - 2 * text_rect.height,
|
||||
)
|
||||
|
||||
|
||||
def on_draw(c: SkiaCanvas):
|
||||
c.paint.textsize = FONT_SIZE
|
||||
|
||||
# Render background
|
||||
c.paint.style = c.paint.Style.FILL
|
||||
c.paint.color = BACKGROUND_COLOR
|
||||
c.draw_rect(c.rect)
|
||||
|
||||
c.paint.color = BORDER_COLOR
|
||||
y_center = c.rect.center.y + ROW_OFFSET * 0.75
|
||||
|
||||
offset = CIRCLE_RADIUS * 2.5
|
||||
|
||||
# Draw trigger buttons
|
||||
y = y_center - ROW_OFFSET * 2.5
|
||||
render_trigger(c, c.rect.center.x - offset, y, triggers["l2"])
|
||||
render_trigger(c, c.rect.center.x + offset, y, triggers["r2"])
|
||||
|
||||
# Draw bumper buttons
|
||||
y = y_center - ROW_OFFSET * 2.15
|
||||
render_flat_button(c, c.rect.center.x - offset, y, buttons["l1"])
|
||||
render_flat_button(c, c.rect.center.x + offset, y, buttons["r1"])
|
||||
|
||||
y = y_center - ROW_OFFSET
|
||||
|
||||
# Draw D-pad buttons
|
||||
render_buttons(
|
||||
c,
|
||||
c.rect.center.x - offset,
|
||||
y,
|
||||
False,
|
||||
["dpad_up", "dpad_right", "dpad_down", "dpad_left"],
|
||||
)
|
||||
|
||||
# Draw compass buttons
|
||||
render_buttons(
|
||||
c,
|
||||
c.rect.center.x + offset,
|
||||
y,
|
||||
True,
|
||||
["north", "east", "south", "west"],
|
||||
)
|
||||
|
||||
# Draw select/start buttons
|
||||
offset = CIRCLE_RADIUS * 0.75
|
||||
y = y_center - ROW_OFFSET / 3
|
||||
render_round_button(c, c.rect.center.x - offset, y, buttons["select"])
|
||||
render_round_button(c, c.rect.center.x + offset, y, buttons["start"])
|
||||
|
||||
# Draw sticks
|
||||
offset = CIRCLE_RADIUS * 1.5
|
||||
y = y_center + ROW_OFFSET
|
||||
render_stick(c, c.rect.center.x - offset, y, buttons["l3"], *sticks["left"])
|
||||
render_stick(c, c.rect.center.x + offset, y, buttons["r3"], *sticks["right"])
|
||||
|
||||
# Draw close text
|
||||
render_close_text(c, c.rect.center.x, c.rect.bot)
|
||||
|
||||
|
||||
def on_mouse(e: MouseEvent):
|
||||
global last_mouse_pos
|
||||
if e.event == "mousedown" and e.button == 0:
|
||||
last_mouse_pos = e.gpos
|
||||
elif e.event == "mousemove" and last_mouse_pos:
|
||||
dx = e.gpos.x - last_mouse_pos.x
|
||||
dy = e.gpos.y - last_mouse_pos.y
|
||||
last_mouse_pos = e.gpos
|
||||
if canvas is not None:
|
||||
canvas.move(canvas.rect.x + dx, canvas.rect.y + dy)
|
||||
elif e.event == "mouseup" and e.button == 0:
|
||||
last_mouse_pos = None
|
||||
|
||||
|
||||
def show():
|
||||
global canvas
|
||||
screen: Screen = ui.main_screen()
|
||||
x = screen.rect.center.x
|
||||
y = screen.rect.center.y
|
||||
canvas = Canvas.from_rect(Rect(x - WIDTH / 2, y - HEIGHT / 2, WIDTH, HEIGHT))
|
||||
canvas.draggable = True
|
||||
canvas.blocks_mouse = True
|
||||
canvas.register("draw", on_draw)
|
||||
canvas.register("mouse", on_mouse)
|
||||
ctx.tags = ["user.gamepad_tester"]
|
||||
|
||||
|
||||
def hide():
|
||||
global canvas
|
||||
if canvas is not None:
|
||||
canvas.unregister("draw", on_draw)
|
||||
canvas.unregister("mouse", on_mouse)
|
||||
canvas.close()
|
||||
canvas = None
|
||||
ctx.tags = []
|
||||
|
||||
|
||||
@mod.action_class
|
||||
class Actions:
|
||||
def gamepad_tester_toggle():
|
||||
"""Toggle visibility of gamepad tester gui"""
|
||||
if canvas is None:
|
||||
show()
|
||||
else:
|
||||
hide()
|
||||
|
||||
def gamepad_tester_button(id: str, is_pressed: bool):
|
||||
"""Indicates that a gamepad button has changed state"""
|
||||
buttons[id] = is_pressed
|
||||
|
||||
def gamepad_tester_trigger(id: str, value: float):
|
||||
"""Indicates that a gamepad trigger has changed state"""
|
||||
triggers[id] = value
|
||||
|
||||
def gamepad_tester_stick(id: str, x: float, y: float):
|
||||
"""Indicates that a gamepad stick has changed state"""
|
||||
sticks[id] = (x, y)
|
||||
@@ -0,0 +1 @@
|
||||
gamepad tester: user.gamepad_tester_toggle()
|
||||
@@ -0,0 +1,48 @@
|
||||
tag: user.gamepad_tester
|
||||
-
|
||||
|
||||
# D-pad buttons
|
||||
gamepad(dpad_up:up): user.gamepad_tester_button("dpad_up", false)
|
||||
gamepad(dpad_up:down): user.gamepad_tester_button("dpad_up", true)
|
||||
gamepad(dpad_right:up): user.gamepad_tester_button("dpad_right", false)
|
||||
gamepad(dpad_right:down): user.gamepad_tester_button("dpad_right", true)
|
||||
gamepad(dpad_down:up): user.gamepad_tester_button("dpad_down", false)
|
||||
gamepad(dpad_down:down): user.gamepad_tester_button("dpad_down", true)
|
||||
gamepad(dpad_left:up): user.gamepad_tester_button("dpad_left", false)
|
||||
gamepad(dpad_left:down): user.gamepad_tester_button("dpad_left", true)
|
||||
|
||||
# Compass buttons
|
||||
gamepad(north:up): user.gamepad_tester_button("north", false)
|
||||
gamepad(north:down): user.gamepad_tester_button("north", true)
|
||||
gamepad(east:up): user.gamepad_tester_button("east", false)
|
||||
gamepad(east:down): user.gamepad_tester_button("east", true)
|
||||
gamepad(south:up): user.gamepad_tester_button("south", false)
|
||||
gamepad(south:down): user.gamepad_tester_button("south", true)
|
||||
gamepad(west:up): user.gamepad_tester_button("west", false)
|
||||
gamepad(west:down): user.gamepad_tester_button("west", true)
|
||||
|
||||
# Select/start buttons
|
||||
gamepad(select:up): user.gamepad_tester_button("select", false)
|
||||
gamepad(select:down): user.gamepad_tester_button("select", true)
|
||||
gamepad(start:up): user.gamepad_tester_button("start", false)
|
||||
gamepad(start:down): user.gamepad_tester_button("start", true)
|
||||
|
||||
# Bumper buttons
|
||||
gamepad(l1:up): user.gamepad_tester_button("l1", false)
|
||||
gamepad(l1:down): user.gamepad_tester_button("l1", true)
|
||||
gamepad(r1:up): user.gamepad_tester_button("r1", false)
|
||||
gamepad(r1:down): user.gamepad_tester_button("r1", true)
|
||||
|
||||
# Stick click buttons
|
||||
gamepad(l3:up): user.gamepad_tester_button("l3", false)
|
||||
gamepad(l3:down): user.gamepad_tester_button("l3", true)
|
||||
gamepad(r3:up): user.gamepad_tester_button("r3", false)
|
||||
gamepad(r3:down): user.gamepad_tester_button("r3", true)
|
||||
|
||||
# Trigger buttons
|
||||
gamepad(l2:change): user.gamepad_tester_trigger("l2", value)
|
||||
gamepad(r2:change): user.gamepad_tester_trigger("r2", value)
|
||||
|
||||
# Sticks axis
|
||||
gamepad(left_xy): user.gamepad_tester_stick("left", x, y*-1)
|
||||
gamepad(right_xy): user.gamepad_tester_stick("right", x, y*-1)
|
||||
Reference in New Issue
Block a user