Events Usage Example

This example demonstrates how to subscribe to and handle VTube Studio events, specifically model movement events.

Full Code

 1"""Example for listening to model moving events in VTube Studio."""
 2
 3import asyncio
 4from vtpy import VTS
 5from vtpy.data.events import (
 6    EventType,
 7    ModelMovedEvent,
 8    ModelMovedEventSubscriptionRequestData,
 9    ModelMovedEventSubscriptionRequestConfig,
10)
11from vtpy.data.common import ErrorData
12from vtpy.error import VTSRequestError
13
14
15async def on_model_moved(event: ModelMovedEvent) -> None:
16    """Handle model moved events."""
17    data = event.data
18    position = data.modelPosition
19
20    print(f"\n=== Model Moved Event ===")
21    print(f"Model ID: {data.modelID}")
22    print(f"Model Name: {data.modelName}")
23    print(f"Position X: {position.positionX:.2f}")
24    print(f"Position Y: {position.positionY:.2f}")
25    print(f"Rotation: {position.rotation:.2f}°")
26    print(f"Size: {position.size:.2f}")
27
28
29async def main():
30    """Main function demonstrating model moved event listening."""
31    # Initialize VTS client
32    vts = VTS(plugin_name="ExamplePlugin", plugin_developer="ExampleDeveloper")
33
34    try:
35        # Connect to VTube Studio at port 8001 and authenticate
36        print("Connecting to VTube Studio at localhost:8001...")
37        auth_token = await vts.start(host="localhost", port=8001, save_auth_token=False)
38        print(f"Successfully authenticated! Token: {auth_token[:20]}...")
39
40        # Register event handler for model moved events
41        print("\nRegistering handler for model moved events...")
42        vts.on_event(EventType.ModelMovedEvent, on_model_moved)
43
44        # Subscribe to model moved events
45        print("Subscribing to model moved events...")
46        data = ModelMovedEventSubscriptionRequestData(
47            subscribe=True, config=ModelMovedEventSubscriptionRequestConfig()
48        )
49        subscription_response = await vts.event_sub_model_moved(data)
50
51        # Keep the connection alive and listen for events
52        try:
53            print("Listening for model moved events. Press Ctrl+C to stop...")
54            await asyncio.Event().wait()  # Wait indefinitely
55        except KeyboardInterrupt:
56            print("\n\nStopping...")
57
58    except ConnectionError as e:
59        print(f"Connection error: {e}")
60        print("Make sure VTube Studio is running and the WebSocket API is enabled.")
61    except ValueError as e:
62        print(f"Authentication error: {e}")
63        print("You may need to approve the authentication request in VTube Studio.")
64    except VTSRequestError as e:
65        print(f"VTube Studio Request error: {e}")
66    except Exception as e:
67        print(f"Unexpected error: {e}", exc_info=True)
68    finally:
69        # Clean up connection
70        if vts.connected:
71            print("\nClosing connection...")
72            await vts.close()
73            print("Disconnected.")
74
75
76if __name__ == "__main__":
77    asyncio.run(main())

Explanation

  1. Import Required Modules

    from vtpy.data.events import (
        EventType,
        ModelMovedEvent,
        ModelMovedEventSubscriptionRequestData,
        ModelMovedEventSubscriptionRequestConfig,
    )
    
  2. Define Event Handler

    async def on_model_moved(event: ModelMovedEvent) -> None:
        """Handle model moved events."""
        data = event.data
        position = data.modelPosition
    
        print(f"Model: {data.modelName}")
        print(f"Position: ({position.positionX:.2f}, {position.positionY:.2f})")
        print(f"Rotation: {position.rotation:.2f}°")
    

    Event handlers must be async functions that accept the event object.

  3. Register Event Handler

    vts.on_event(EventType.ModelMovedEvent, on_model_moved)
    

    Register the handler with the VTS client.

  4. Subscribe to Events

    data = ModelMovedEventSubscriptionRequestData(
        subscribe=True,
        config=ModelMovedEventSubscriptionRequestConfig()
    )
    await vts.event_sub_model_moved(data)
    

    Subscribe to model moved events from VTube Studio.

  5. Keep Connection Alive

    await asyncio.Event().wait()  # Wait indefinitely
    

    Keep the connection alive to receive events. The script will run until interrupted.

Expected Output

When run successfully, you should see output like:

Connecting to VTube Studio at localhost:8001...
Successfully authenticated! Token: abc123def456...

Registering handler for model moved events...
Subscribing to model moved events...
Listening for model moved events. Press Ctrl+C to stop...

=== Model Moved Event ===
Model ID: model-123
Model Name: MyModel
Position X: 0.12
Position Y: -0.05
Rotation: 2.34°
Size: 1.00

=== Model Moved Event ===
Model ID: model-123
Model Name: MyModel
Position X: 0.13
Position Y: -0.04
Rotation: 2.35°
Size: 1.00

The events will continue to fire as the model moves in VTube Studio.

Stopping the Script

Press Ctrl+C to stop the script. The KeyboardInterrupt exception is caught, and the connection is properly closed.