Keyboard shortcuts

Press or to navigate between chapters

Press S or / to search in the book

Press ? to show this help

Press Esc to hide this help

Controller

The dice-rs-controller crate is a GTK 4 desktop application for managing GoDice devices with a graphical interface and 3D dice rendering.

Features

  • Auto-scan on startup with manual rescan button
  • Dice list showing all connected dice with face value, battery, and color
  • Dice type selector - dropdown to choose between D6, D20, D10, D10X, D4, D8, D12
  • 3D dice rendering using OpenGL (glow + glam) with real-time orientation from accelerometer data and per-type geometry
  • LED controls - color pickers, set/pulse/off buttons
  • Tap controls - enable/disable tap and double tap notifications
  • Battery indicator with visual gauge
  • Roll history showing recent face values
  • Tap indicator flashing on tap events
  • Reconnect support for dropped connections

Building

The controller requires GTK 4 development libraries:

# Ubuntu/Debian
sudo apt install libgtk-4-dev

# Build
cargo build -p dice-rs-controller

Running

cargo run -p dice-rs-controller

The application window appears with a scan button and an empty dice list. Connected dice appear as rows with interactive controls.

Architecture

flowchart TB
    app["Application
    (gtk4::Application)"]
    window["MainWindow
    (scan, dice list)"]
    row["DiceRow
    (per-dice UI)"]
    controller["EventController
    (async → GTK bridge)"]
    dice3d["Dice3D
    (OpenGL renderer)"]
    models["Models
    (DiceModelTrait)"]
    led["LedControls
    (color pickers)"]
    tap["TapControls
    (tap switches)"]
    battery["BatteryIndicator"]
    history["RollHistory"]
    face["FaceDisplay"]
    typesel["DropDown
    (dice type)"]

    app --> window
    window --> row
    row --> controller
    row --> dice3d
    dice3d --> models
    row --> led
    row --> tap
    row --> battery
    row --> history
    row --> face
    row --> typesel
    typesel -->|set_dice_type| dice3d

EventController

The EventController bridges async dice events into the GTK main loop. It runs a background tokio task that receives DiceEvents and sends UI updates through an mpsc channel to the GTK main thread. This avoids blocking the UI while waiting for BLE events.

Dice Type Selection

Each DiceRow includes a DropDown widget for selecting the dice type (D6, D20, D10, D10X, D4, D8, D12). Changing the selection calls dice.set_dice_type() on the dice-rs library handle (client-side setting, no BLE command) and updates the 3D model geometry via Dice3D::set_dice_type().

The dice type controls how accelerometer data is interpreted into face values using vector tables and shell transforms. See Architecture for details on the interpretation pipeline.

3D Dice Models

The DiceModelTrait defines the interface for 3D geometry generation. Each dice type has a dedicated model implementation:

TypeShapeFacesVertices
D6Cube6 quads24
D4Tetrahedron4 triangles12
D8Octahedron8 triangles24
D10/D10XPentagonal trapezohedron10 kites60
D12Dodecahedron12 pentagons72
D20Icosahedron20 triangles60

The model_for_type() factory function selects the appropriate model based on DiceType. The DiceRenderer uploads vertex data (positions, normals, UVs, face IDs) to OpenGL and renders with diffuse lighting and edge highlighting. D6 faces additionally render procedural pips via the fragment shader; other die types show face color with edges only.

When the dice type changes at runtime, the Dice3D widget discards the existing renderer and re-initializes with the new model geometry on the next render frame.