simvx.core.scripted_demo

Scripted demo playback — automated input sequences with narration and assertions.

Drive a game/UI scene with pre-recorded steps: move cursor, click, type text, press keys, wait, assert state, and show narration overlays. Useful for creating self-playing demos, tutorials, and integration tests.

Usage: from simvx.core.scripted_demo import DemoRunner, MoveTo, Click, Narrate, Assert

steps = [
    Narrate("Welcome to the demo!", duration=2.0),
    MoveTo(200, 150, duration=0.5),
    Click(200, 150),
    Assert(lambda g: g.board[0][0] == "X", "Cell should be X"),
]
runner = DemoRunner(steps, speed=2.0)
game.add_child(runner)

Module Contents

Classes

MoveTo

Smoothly move the virtual cursor to a screen position.

Click

Move to position then click (press + release).

TypeText

Type a string character by character.

PressKey

Press and hold a key for a duration.

Wait

Pause playback for a duration.

Assert

Run a check function against the game node (parent of DemoRunner).

Do

Execute an action against the game node (parent of DemoRunner).

Scroll

Scroll the mouse wheel at a position.

Narrate

Display narration text at the bottom of the screen.

DemoRunner

Plays a scripted sequence of demo steps, injecting input and drawing overlays.

Data

API

simvx.core.scripted_demo.log[source]

‘getLogger(…)’

simvx.core.scripted_demo.__all__

[‘MoveTo’, ‘Click’, ‘TypeText’, ‘PressKey’, ‘Wait’, ‘Assert’, ‘Do’, ‘Scroll’, ‘Narrate’, ‘DemoRunner…

class simvx.core.scripted_demo.MoveTo[source]

Smoothly move the virtual cursor to a screen position.

x: float

None

y: float

None

duration: float

0.5

class simvx.core.scripted_demo.Click[source]

Move to position then click (press + release).

x: float

None

y: float

None

button: int

1

class simvx.core.scripted_demo.TypeText[source]

Type a string character by character.

text: str

None

delay_per_char: float

0.05

class simvx.core.scripted_demo.PressKey[source]

Press and hold a key for a duration.

key: int

None

hold_duration: float

0.1

class simvx.core.scripted_demo.Wait[source]

Pause playback for a duration.

duration: float

None

class simvx.core.scripted_demo.Assert[source]

Run a check function against the game node (parent of DemoRunner).

check_fn: Any

None

message: str = <Multiline-String>
actual_fn: Any

None

class simvx.core.scripted_demo.Do[source]

Execute an action against the game node (parent of DemoRunner).

Like Assert but semantically different — never fails on return value. In test_mode, exceptions propagate; in interactive mode, they’re logged.

action: Any

None

message: str = <Multiline-String>
class simvx.core.scripted_demo.Scroll[source]

Scroll the mouse wheel at a position.

x: float

None

y: float

None

dy: float

None

dx: float

0.0

class simvx.core.scripted_demo.Narrate[source]

Display narration text at the bottom of the screen.

text: str

None

duration: float

2.0

class simvx.core.scripted_demo.DemoRunner(steps: list, test_mode: bool = False, on_complete: collections.abc.Callable | None = None, speed: float | None = None, speed_mode: int = 0, delay_between_steps: float = 0.15, **kwargs)[source]

Bases: simvx.core.engine.Node

Plays a scripted sequence of demo steps, injecting input and drawing overlays.

Add as a child of the game/scene root. In test_mode, hotkeys are disabled and assertions raise on failure.

Args: steps: List of step dataclasses to execute in order. test_mode: If True, skip hotkeys and raise on assertion failure. on_complete: Optional callback invoked when all steps finish. speed: Explicit speed override. If set, takes precedence over speed_mode. speed_mode: Speed preset index (0=slow 0.5x, 1=fast 3x, 2=instant 50x). Default 1. delay_between_steps: Natural pause (seconds) between steps. Default 0.15.

Initialization

classmethod register_step_handler(step_type: type, handler: collections.abc.Callable)[source]

Register a handler for a custom step type.

Handler signature: (runner: DemoRunner, step, dt: float) -> None. The handler must call runner._advance() when the step is complete.

property current_step_index: int
property total_steps: int
property is_done: bool
property failures: list[str]
physics_process(dt: float)[source]
draw(renderer)[source]
classmethod run_headless(scene: simvx.core.engine.Node, steps: list, *, speed: float = 50.0, screen_size: tuple[int, int] = (800, 600), max_frames: int = 20000, delay_between_steps: float = 0.0) bool[source]

Run a demo headlessly and return True if all steps pass.

Creates a DemoRunner in test_mode, adds it to scene, and advances frames via SceneRunner until completion or max_frames is reached.

classmethod run_visual(scene: simvx.core.engine.Node, steps: list, *, speed: float | None = None, speed_mode: int = 0, title: str = 'Demo', width: int = 800, height: int = 600, backend: str | None = None)[source]

Run a demo visually with the Vulkan App.

Lazily imports simvx.graphics.App to keep core free of graphics deps.

strict_errors: ClassVar[bool]

True

script_error_raised

‘Signal(…)’

classmethod __init_subclass__(**kwargs)
property name: str
property process_mode: simvx.core.descriptors.ProcessMode
reset_error() None
add_child(node: simvx.core.node.Node) simvx.core.node.Node
remove_child(node: simvx.core.node.Node)
reparent(new_parent: simvx.core.node.Node)
get_node(path: str) simvx.core.node.Node
find_child(name: str, recursive: bool = False) simvx.core.node.Node | None
find(node_type: type, recursive: bool = True) simvx.core.node.Node | None
find_all(node_type: type, recursive: bool = True) list
property path: str
add_to_group(group: str)
remove_from_group(group: str)
is_in_group(group: str) bool
ready() None
enter_tree() None
exit_tree() None
process(dt: float) None
input_event(event: simvx.core.events.InputEvent) None
input(event: simvx.core.events.TreeInputEvent) None
unhandled_input(event: simvx.core.events.TreeInputEvent) None
start_coroutine(gen: simvx.core.descriptors.Coroutine) simvx.core.descriptors.CoroutineHandle
stop_coroutine(gen_or_handle)
clear_children()
destroy()
property app
property tree: simvx.core.scene_tree.SceneTree
get_tree() simvx.core.scene_tree.SceneTree
__getitem__(key: str)
classmethod get_properties() dict[str, simvx.core.descriptors.Property]
__repr__()