simvx.core.ui.touch_controller

The on-screen controller, which is a controller.

TouchController draws a stick and buttons on the glass and publishes what the player does with them as a real pad. A game that binds Controller.A and Controller.LEFT_STICK gets touch play by adding one node and writing nothing else, because nothing downstream knows the pad is drawn::

def on_ready(self):
    self.add_child(TouchController())

It is a pad in every way a game can observe. While it is visible it appears in Input.controllers and fires controller_connected like any controller, so a lobby enumerating pads sees it; its :attr:~simvx.core.input.enums. ControllerSource is VIRTUAL, which is what a lobby filters on when it wants only physical ones. It leaves the mapping the moment it is hidden.

Both pads at once is not a special case. With a controller plugged in and this on screen, Input.controllers holds two entries with different sources, and a binding that names no unit resolves against every pad at once: any pad’s press counts and the largest-magnitude axis wins. So a player who picks up the controller mid-game keeps playing, two thumbs and a stick do not fight, and a game that genuinely wants one pad pins a binding to it with Controller.A.on(pad) or pairs it to a player.

It never switches the input method. A device-sourced pad does that; this one does not, precisely so it cannot hide itself under the player’s thumb. It does go away when a real controller is used, which is the other half of the same rule.

It is a canvas layer, not a control. An on-screen pad that scrolled with the world would be a defect rather than a choice, so the screen pinning is built in rather than being a wrapper the game has to remember; layer is the ordinary :class:~simvx.core.nodes_2d.canvas.CanvasLayer knob for putting it above or below the rest of the HUD.

Module Contents

Classes

TouchControllerLayout

Which controls a :class:TouchController puts on the glass.

TouchController

An on-screen controller, published as a controller.

Data

API

simvx.core.ui.touch_controller.__all__

[‘TouchController’, ‘TouchControllerLayout’]

simvx.core.ui.touch_controller.VIRTUAL_CONTROLLER_NAME

‘On-screen controller’

simvx.core.ui.touch_controller.VIRTUAL_CONTROLLER_GUID

‘simvx:touch-controller’

class simvx.core.ui.touch_controller.TouchControllerLayout[source]

Bases: enum.StrEnum

Which controls a :class:TouchController puts on the glass.

A layout is a choice of controls, never a set of coordinates: the geometry follows the window and the touch-target floor, so a game says what it needs a player to be able to do and nothing about where.

What differs between them is only how the player moves, and whether there is a second stick to aim with. A, B and Start are on all three, because a real pad has face buttons whatever its stick arrangement and a touch player must always be able to reach the pause menu.

Members: STICK_AND_BUTTONS: An analogue left stick. The default, and what most games with a character and an action want. TWIN_STICK: A right stick as well, for a game that aims with one. DPAD_AND_BUTTONS: A four-way D-pad in place of the left stick, for a grid or platform game where an analogue reading is noise.

Initialization

Initialize self. See help(type(self)) for accurate signature.

STICK_AND_BUTTONS

‘stick_and_buttons’

TWIN_STICK

‘twin_stick’

DPAD_AND_BUTTONS

‘dpad_and_buttons’

__new__(*values)
__add__()
__contains__()
__delattr__()
__dir__()
__eq__()
__format__()
__ge__()
__getattribute__()
__getitem__()
__getnewargs__()
__getstate__()
__gt__()
__hash__()
__iter__()
__le__()
__len__()
__lt__()
__mod__()
__mul__()
__ne__()
__reduce__()
__reduce_ex__()
__repr__()
__rmod__()
__rmul__()
__setattr__()
__sizeof__()
__str__()
__subclasshook__()
capitalize()
casefold()
center()
count()
encode()
endswith()
expandtabs()
find()
format()
format_map()
index()
isalnum()
isalpha()
isascii()
isdecimal()
isdigit()
isidentifier()
islower()
isnumeric()
isprintable()
isspace()
istitle()
isupper()
join()
ljust()
lower()
lstrip()
partition()
removeprefix()
removesuffix()
replace()
rfind()
rindex()
rjust()
rpartition()
rsplit()
rstrip()
split()
splitlines()
startswith()
strip()
swapcase()
title()
translate()
upper()
zfill()
__deepcopy__(memo)
__copy__()
name()
value()
class simvx.core.ui.touch_controller.TouchController(**kwargs)[source]

Bases: simvx.core.nodes_2d.canvas.CanvasLayer

An on-screen controller, published as a controller.

Add one and a game that already reads Controller buttons and sticks bindings is playable with two thumbs; there is nothing else to wire up.

Attr:

layout says how the player moves and :attr:buttons which buttons they get, and neither takes a coordinate.

Example: def on_ready(self): self.add_child(TouchController()) # or, for a twin-stick game with four face buttons: self.add_child(TouchController( layout=”twin_stick”, buttons=(Controller.A, Controller.B, Controller.X, Controller.Y), ))

Initialization

layout

‘Property(…)’

buttons

‘Property(…)’

layer

‘Property(…)’

auto_hide

‘Property(…)’

visible

‘Property(…)’

property controller: simvx.core.input.devices.ControllerDevice | None[source]

This pad as a :class:~simvx.core.input.devices.ControllerDevice, or None.

None while the pad is not on screen, when it is not in Input.controllers either.

property pointer_types: frozenset[simvx.core.input.enums.PointerType] | None[source]

The kinds of pointer the drawn controls answer, fingers alone by default.

A mouse click in the pad’s area passes through to the game, so a desktop game can shoot where the stick is drawn. A game tested with a mouse, or played with a pen, widens it: pad.pointer_types = frozenset({PointerType.TOUCH, PointerType.MOUSE}). None answers every pointer.

on_enter_tree() → None[source]
on_exit_tree() → None[source]
class Band

Bases: enum.IntEnum

BACKGROUND

None

WORLD

0

UI

1000

OVERLAY

2000

__abs__()
__add__()
__and__()
__bool__()
__ceil__()
__delattr__()
__dir__()
__divmod__()
__eq__()
__float__()
__floor__()
__floordiv__()
__format__()
__ge__()
__getattribute__()
__getnewargs__()
__getstate__()
__gt__()
__hash__()
__index__()
__int__()
__invert__()
__le__()
__lshift__()
__lt__()
__mod__()
__mul__()
__ne__()
__neg__()
__new__()
__or__()
__pos__()
__pow__()
__radd__()
__rand__()
__rdivmod__()
__reduce__()
__reduce_ex__()
__repr__()
__rfloordiv__()
__rlshift__()
__rmod__()
__rmul__()
__ror__()
__round__()
__rpow__()
__rrshift__()
__rshift__()
__rsub__()
__rtruediv__()
__rxor__()
__setattr__()
__sizeof__()
__str__()
__sub__()
__subclasshook__()
__truediv__()
__trunc__()
__xor__()
as_integer_ratio()
bit_count()
bit_length()
conjugate()
class denominator
class imag
is_integer()
class numerator
class real
to_bytes()
__deepcopy__(memo)
__copy__()
name()
value()
offset

‘Property(…)’

rotation

‘Property(…)’

scale_val

‘Property(…)’

follow_viewport

‘Property(…)’

environment

‘Property(…)’

post_processed

‘Property(…)’

property transform_render_dirty: bool
strict_errors: ClassVar[bool]

True

dev_checks: ClassVar[bool]

None

dev_warnings: ClassVar[bool]

None

freeze_check_interval: ClassVar[float]

1.0

script_error_raised

‘Signal(…)’

dynamic: bool

False

update_mode

‘Property(…)’

focus_mode

‘Property(…)’

drag_threshold

‘Property(…)’

focus_entered

‘Signal(…)’

focus_exited

‘Signal(…)’

__properties__: ClassVar[dict[str, simvx.core.descriptors.Property]]

None

classmethod __init_subclass__(**kwargs)
property name: str
property visible_in_tree: bool
property input_player: simvx.core.input.players.InputPlayer
property input_context: simvx.core.input.contexts.InputContext | None
reset_error() → None
add_child(node: simvx.core.node.T) → simvx.core.node.T
remove_child(node: simvx.core.node.Node) → None
reparent(new_parent: simvx.core.node.Node)
node_at(path, default=_NO_DEFAULT)
find(target, *, direct: bool = False)
find_all(target, *, direct: bool = False)
expect(target, *, direct: bool = False)
ancestor(target)
walk(*, include_self: bool = True) → collections.abc.Iterator[simvx.core.node.Node]
property path: str
property is_scene_root: bool
add_to_group(group: str)
remove_from_group(group: str)
is_in_group(group: str) → bool
on_ready() → None
on_update(dt: float) → None
on_fixed_update(dt: float) → None
on_draw(canvas) → None
on_draw_3d(gizmos) → None
on_picked(event: simvx.core.input.events.PickEvent) → bool | None
start_coroutine(gen: simvx.core.descriptors.Coroutine) → simvx.core.descriptors.CoroutineHandle
stop_coroutine(gen_or_handle)
property focused: bool
property focus_rect: tuple[float, float, float, float] | None
drag_threshold_for(pointer_type: simvx.core.input.enums.PointerType | str) → float
grab_focus() → None
release_focus() → None
capture_pointer(pointer_id: int | None = None) → None
release_pointer(pointer_id: int | None = None) → None
queue_redraw() → None
property render_dirty: bool
clear_children()
destroy()
property destroying: bool
call_deferred(method: collections.abc.Callable[..., Any], *args: Any) → None
property app
property tree: simvx.core.scene_tree.SceneTree
property viewport_size: simvx.core.math.types.Vec2
property viewport_insets: tuple[float, float, float, float]
property physics
property physics_2d
__getitem__(key: str)
classmethod get_properties() → dict[str, simvx.core.descriptors.Property]
__repr__()