|
VR-Engage
2.2
|
Purpose: This example demonstrates how to create custom heads-up display (HUD) overlays using Qt Quick/QML technology for VR-Engage player stations. It shows the pattern for binding VR-Engage state attributes to QML properties, processing simulation messages to extract entity information, and creating responsive animated HUD elements.
Observable Behavior: When running this example, you will see a vehicle status indicator in the lower-left corner showing a tank silhouette. When mobility damage is applied, the tank treads flash red, and when firepower damage is applied, the tank turret flashes red. For human roles, an animated antenna icon appears when the radio is transmitting, with smooth color animations using sinusoidal easing.
Prerequisites: Understanding of the Player Station Framework and familiarity with the Player Attribute Store. Basic Qt/QML knowledge (properties, signals, bindings) and knowledge of the VR-Engage message system are required.
Related Examples: The State Example provides more comprehensive state and QML integration, while Notification Example covers message system and user feedback patterns. The Vehicle Blinker Example demonstrates frontend/backend state synchronization.
This example implements QML overlay integration using DtQtQuickOverlay for 2D UI over 3D graphics. The framework-provided component handles QML loading and rendering with automatic data binding between C++ attributes and QML properties. It also demonstrates both vehicle and human role QML overlays.
The example covers state attribute extension by creating custom attributes beyond the standard set. The DtDriverQmlHudComponent manages vehicle damage state attributes and demonstrates hierarchical attribute structure (vehicle-status.mobility-kill) with attribute initialization in postInitialize().
Message-driven updates process simulation messages for HUD data by listening for SimulationStateMessage containing entity appearance bits and using the DtAppearance helper to extract semantic damage information. The data binding pattern then provides automatic UI updates from state changes with QML properties bound to attributes configured in the role.
The plugin registers the custom HUD component with VR-Engage's factory system:
The component type string DtDriverQmlHudComponentType is "DtDriverQmlHudComponent", and logging provides visibility during plugin loading. The extern "C" declaration ensures proper symbol export for dynamic loading.
The component monitors simulation state messages to extract damage information:
Messages are the primary mechanism for receiving entity state updates, while DtVreMessageDelegate provides type-safe callback registration. The handler must be removed in shutdown() to prevent dangling references.
The component creates nested attributes that QML will bind to:
The postInitialize() method runs after all components exist, making it safe to access the attribute store. The bracket operator [] creates attributes if they don't exist, while initial values prevent undefined behavior before the first message arrives. The QML overlay component will bind to these exact attribute paths.
The component extracts damage state from simulation messages:
The entity ID check prevents processing other entities' state, while DtAppearance abstracts DIS appearance bit field complexity. Attribute updates automatically trigger QML property updates without manual notification, and returning HANDLED allows other components to process the message.
The role Lua file configures both the QML overlay and supporting component:
The role inherits from the standard driver role and adds custom components. Priority numbers determine initialization order, with lower values initializing first (4 before 10). The bindQmlPropertyToAttribute table maps QML property names to attribute paths, while qmlDataItemObjectName identifies which QML Item receives the bound properties. The two components work together: one manages state, one renders UI.
The QML file defines the visual overlay with data binding:
The state item serves as the central object for all bound properties. Property change handlers react to C++ attribute updates and trigger animations declaratively, with QML handling timing and interpolation. The hudScale() function adapts element sizes to different screen resolutions.
sequenceDiagram
participant SM as Simulation Message
participant HC as HUD Component
participant AS as Attribute Store
participant QO as Qt Quick Overlay
participant QML as QML Interface
SM->>HC: SimulationStateMessage
HC->>HC: Extract appearance bits
HC->>AS: Update vehicle-status.mobility-kill
HC->>AS: Update vehicle-status.firepower-kill
AS->>QO: Attribute change notification
QO->>QML: Bind attributes to QML properties
QML->>QML: Update UI & trigger animations
DtDriverQmlHudComponentDtDriverQmlHudComponent and DtQtQuickOverlayDtDriverQmlHudComponent creates attribute hierarchyDtQtQuickOverlay loads QML file and binds propertiesSimulationStateMessageDtDriverQmlHudComponent::handleSimState() filters and processesBuild the example (see Environment Setup & Build Guide):
Install the plugin to the VR-Engage installation:
This copies the plugin to the appropriate location:
<VR-Engage-Install-Dir>\plugins64\vrEngage\release\Verify installation:
For quick standalone testing without creating a separate VR-Forces scenario, you can run VR-Engage with the qmlHud.sms example simulation model set as the default. This loads the example roles and data installed under data/simulationModelSets/examples/qmlHud:
When connecting to a separate VR-Forces exercise instead, use the scenario-based configuration described below.
Create a test scenario:
examples/qmlHud.sms simulation model set"Initializing QML HUD components"Verification: The HUD demonstrates real-time data binding between C++ component state and QML visual elements, with automatic property updates and smooth visual transitions for both vehicle damage states and human radio transmission states.
| Symptom | Diagnosis | Solution |
|---|---|---|
| HUD not visible | QML file not found or wrong entity type | Verify entity is LAV III APC with "Driver" role selected |
| Properties not updating | Attribute name mismatch | Check exact paths in Lua config match C++ code |
| Wrong role available | Entity not configured for QML HUD | Use LAV III APC entity with "Driver" role only |
| Crash on shutdown | Handler not removed | Verify removeHandler() in shutdown() |
| Animation not playing | Property not triggering | Add console.log() in QML to verify property changes |
Add diagnostic output to component:
Plugin not loading:
<VR-Engage-Install-Dir>\plugins64\vrEngage\release\dumpbin /dependents*.log file in the MAK log directory, typically C:/MAK/logs) for error messages| Class | Base Class | Purpose | Header |
|---|---|---|---|
DtDriverQmlHudComponent | DtPlayerComponent | Vehicle damage state tracking and attribute publishing | driverQmlHudComponent.h |
DtQtQuickOverlay | DtPlayerComponent | Framework-provided QML overlay rendering | (VR-Engage framework) |
DtVreMessageManager::addHandler() - Register message handler callbacksDtVreMessageManager::removeHandler() - Unregister message handlersDtPlayerStation::playerAttributeStore() - Access centralized attribute repositoryDtAttributeHandle::set<T>() - Type-safe attribute value assignmentDtAppearance::immobilized() / firePowerDisabled() - DIS appearance bit interpretationDtPlayerStationApp::componentFactory().addCreator<T>() - Component factory registration| Attribute Path | Type | Description | Updated By |
|---|---|---|---|
vehicle-status.mobility-kill | bool | True when vehicle is immobilized | DtDriverQmlHudComponent |
vehicle-status.firepower-kill | bool | True when vehicle weapons are disabled | DtDriverQmlHudComponent |
| Category | Libraries |
|---|---|
| VR-Engage | vrePlayerStation, vreMessageManager, vreMessages, vreCommonComponents, vreUtil |
| Qt | Qt5::Core, Qt5::Qml, Qt5::Quick |
| VR-Link | vlutil (includes DtAppearance helper) |
exampleQmlHud.dll (Windows)plugins64/vrEngage/release/qmlHud.sms simulation model set| File Type | Location |
|---|---|
| QML overlays | <VR-Engage-Install-Dir>/data/UI/examples/exampleQmlHud*.qml |
| Role configs | <VR-Engage-Install-Dir>/data/simulationModelSets/examples/qmlHud/roles/*.lua |
| SMS file | <VR-Engage-Install-Dir>/data/simulationModelSets/examples/qmlHud.sms |
Related Documentation: