|
VR-Engage
2.2
|
Role configuration connects C++ components to the runtime system, enabling users to select roles from the engagement interface and allowing configuration without recompilation. This section covers role definition files, reusable configuration modules (often referred to as component groups), parameter systems, entity integration, and deployment patterns. Understanding role configuration is important for making toolkit extensions available to end users and for customizing existing roles to meet specific training requirements.
The role system bridges compiled C++ components and runtime configuration through a layered architecture. At the lowest level, C++ components implement functionality. Reusable configuration modules ("component groups") organize related components into units that can be shared across roles. Role definition files assemble these modules and individual components into complete player experiences. Entity files bind roles to specific vehicle types and allow parameter customization. This layered approach enables maximum reuse while supporting vehicle-specific customization.
| Layer | File Type | Contents |
|---|---|---|
| Entity | .entity | Entity definition, role bindings, parameter overrides |
| Role | .lua | Role definition, display layouts, includes, components table |
| C++ Components | C++ | DtDriverControlLogic, DtObserverUpdater, DtAudioUpdater, etc. |
When a user engages an entity and selects a role, VR-Engage follows this resolution process: the entity file identifies available roles and their configuration sources, the role file specifies which reusable configuration modules to pull in and how to configure the display, those modules and the role file together enumerate the specific C++ components to create, and finally the framework instantiates each component with merged configuration from all layers. Parameter values flow down through the layers, with entity-level overrides taking precedence over role defaults, which take precedence over component defaults.
This section covers the file formats and mechanisms for defining roles: role definition files, reusable component groups, and how the loader composes them into complete configurations.
Role definition files are Lua scripts located in data/simulationModelSets/VR-Engage/roles/. Each file defines a complete role configuration including display layouts, component instantiation, and default parameter values. The Lua format enables conditional logic, includes, and computed values while remaining human-readable.
A minimal role file specifies the components required for the role and at least one display layout. The components table lists component entries that reference registered C++ component types. Each entry can include parameters that override component defaults.
The componentType field references the type name registered with the component factory during plugin initialization. This name must match exactly—the framework performs a case-sensitive lookup in the factory registry. Other fields in the component entry become configuration parameters passed to the component's initialize() method through the DtInitTable. For a detailed description of component lifecycle and initialization, see Player Station Framework.
Display layouts define how the visual output is organized across physical displays. Each layout specifies one or more channels with their screen positions and dimensions. Layouts support both single-monitor desktop configurations and multi-display setups for full-dome or multi-projector systems.
Channel names are referenced by overlay configurations and observer updaters. Channels are a VR-Vantage concept that map rendering viewports to screen regions; VR-Engage role configurations use them to control how the 3D view is displayed. The fovOffset parameter adjusts the field of view for peripheral displays in multi-monitor setups. The stereo flag enables stereoscopic rendering for VR headsets. VR-Engage selects the appropriate layout based on user preference and hardware detection.
Roles often share common functionality like radio systems or action menus. The includes table specifies additional Lua files to load and merge into the role configuration. This promotes reuse and ensures consistency across roles that share capabilities.
The path macro @(vre-roles-dir) resolves to the roles directory within the active simulation model set. Using this macro ensures paths remain valid across different installation locations.
Included files follow the same structure as role files. When files are included, their components entries merge with the including file's entries. If the same component name appears in multiple files, the including file's values take precedence. This enables included files to provide defaults that roles can override.
Roles specify QML and GL Studio overlays that provide heads-up displays, instrument panels, and other visual feedback. Overlay configuration associates QML files with display channels and provides initial property values.
The qmlFile path is resolved relative to the data/UI folder within the installation directory. For example, "HUDS/pilotHud.qml" resolves to data/UI/HUDS/pilotHud.qml.
The properties table provides initial values for QML properties exposed by the overlay. These values are accessible through the QML context and can be bound to UI elements. Changes to property values at runtime automatically update bound UI elements through Qt's property binding system.
In the runtime system there is no special "componentGroup" keyword or type. Instead, component groups are a documentation term for reusable Lua files that export shared components tables. These files are pulled into roles through the standard include and merge mechanism, and their components become part of the role just like locally defined components.
Component groups are defined in Lua files within the simulation model set. Each file exports a components table that specifies the components it contains and their default configurations. By convention, these files live in the roles/devices/ directory, though they can be placed anywhere as long as the role's includes table references the correct path.
Component groups are typically consumed via the role's includes table. The loader script (data/factory/scripts/loadDefinition.lua) reads the role file, loads each included Lua file with loadTableFile(), and merges the resulting tables with mergeDefinitions(). Any components entries from included files are merged into the role's own components table.
Parameters specified directly in the role file override parameters from included component group files. This enables roles to customize shared behavior without modifying the group definitions.
Role composition is implemented entirely in Lua by the loader script (data/factory/scripts/loadDefinition.lua). There is no special file format or runtime type for component groups; everything is regular Lua tables that get merged together.
At a high level, the loader:
resolvePath(), which expands macros like @(vre-roles-dir) and searches the active simulation model set paths.loadTableFile().includes via mergeExternalIncludeFiles(), which loads each included Lua file and merges its contents into the role definition with mergeDefinitions().inherits chain to build an inheritance list of role definitions, applying mergeExternalIncludeFiles() and expandExternalDisplayFiles() to each parent.mergeDefinitions() to merge each definition from the inheritance chain, combining appModes, roles, displayLayouts, menuConfig, components, and connectors according to well-defined rules.The result of this process is a fully composed role definition that the runtime uses as the source for creating player configurations.
When a player is actually created, getPlayerConfiguration() clones the composed role definition into a player table, applies any display layout and parameter overrides, sorts menus and components, and then returns the final configuration to C++.
When role definition debugging is enabled, getPlayerConfiguration() also calls savePlayerDefinition(), which serializes the fully composed player table and writes it to a debug folder under the roles directory ($(vre-roles-dir)/debug). These files are regular Lua tables and are the easiest way to see the exact set of components, menus, and parameter values that will be instantiated at runtime for a given role and display layout.
The role parameter system enables runtime configuration of component behavior without recompilation. Parameters can be overridden at multiple levels of the configuration hierarchy and are read during component initialization.
Components read parameters from the DtInitTable passed to their initialize() method. The table contains merged values from all configuration layers with appropriate precedence.
The default values in findDataOr<bool>(), findDataOr<double>(), and similar templated methods should match the defaults declared in the \vreRoleParam tags. This ensures consistent behavior whether the parameter is explicitly configured or uses the default.
The configuration system supports several data types with corresponding lookup methods:
| Type | Lua Syntax | C++ Lookup Method | Example |
|---|---|---|---|
bool | true / false | findDataOr<bool>() | enabled = true |
int | 42 | findDataOr<int>() | count = 10 |
double | 3.14 | findDataOr<double>() | speed = 55.5 |
float | 1.5 | findDataOr<float>() | scale = 1.0 |
string | "text" | findDataOr<std::string>() | name = "Player" |
table | { ... } | findDataOr<DtInitTable>() | options = { a = 1 } |
String parameters require quotes in Lua configuration. Numeric values can be integers or floating-point. Boolean values are the Lua keywords true and false (lowercase). Tables enable structured configuration for complex parameters.
Entity files bind roles to specific vehicle types and enable per-vehicle parameter customization. The <vrEngageRoles> section within an entity definition specifies which roles are available when engaging that entity type and how those roles should be configured.
The entity file's role section lists available roles with their configuration sources and display options.
Role binding attributes control how the role appears in the engagement interface:
| Attribute | Purpose | Example |
|---|---|---|
paramName | Display name in role selection UI | "Driver" |
slotName | Internal slot identifier for multi-crew coordination | "Driver" |
unlisted | Hide from role selection (for internal roles) | "false" |
defaultDisplayLayout | Initial display configuration | "1 Screen Horizontal" |
The role file path uses the @(vre-roles-dir) macro to locate the role definition within the simulation model set. The path is relative to the macro expansion point.
Parameter overrides enable vehicle-specific customization without creating separate role files. Each <parameterOverride> element specifies a component name, parameter name, and new value using dot notation.
The component name corresponds to the key in the role file's components table. The parameter name matches the configuration namespace constant. Values follow Lua syntax appropriate for the parameter type.
Multiple overrides can target the same component. Overrides are processed in order, with later overrides taking precedence if the same parameter is specified multiple times.
When the same parameter is configured at multiple levels, the system applies a clear precedence order (highest to lowest):
<parameterOverride> elementscomponents entriesEntity-level overrides have the highest precedence, enabling vehicle-specific tuning without modifying shared role files. C++ default values serve as the fallback when no configuration specifies a value. This layered approach balances standardization with customization flexibility.
VR-Engage supports multi-crew vehicles where multiple players occupy different roles on the same entity. The role system coordinates crew positions through slot assignments and provides mechanisms for switching between roles.
Each role in an entity file can specify a slotName attribute that corresponds to an embarkation slot defined in the entity's <embarkationSlots> configuration. When a player engages an entity in a particular role, VR-Engage associates them with that slot. Two players can concurrently play different roles on the same vehicle—for example, one player as Driver and another as Gunner or Commander.
The slotName values reference embarkation slots defined elsewhere in the entity file. When a player embarks on a vehicle while playing a human character, VR-Engage presents available roles based on these slot configurations. For details about embarkation configuration, see Embarkation Configuration and "Appendix B. Embarkation Slot
Configuration in VR-Engage" in the VR-Engage User Guide.
Players can switch between available roles on their current vehicle without returning to the Choose Role panel. Ground vehicles configured with multiple roles allow players to change roles while embarked using the Action Menu or keyboard shortcuts ([ for previous role, ] for next role).
For end-user procedures, see "3.4.3 Switching Roles on a Vehicle" in the VR-Engage User Guide.
Meta-roles combine multiple related sub-roles into a single logical role that players can select from the Choose Role panel. Once engaged in a meta-role, players can quickly switch between sub-roles using keyboard shortcuts without returning to the role selection interface.
For example, the GTK Boxer CRV Commander role is a meta-role containing Commander Hatch and Commander Sight sub-roles. Players toggle between these positions with a single key press.
The DtMetaRoleControlLogic component manages sub-role switching. It instantiates player station instances for each sub-role and provides input bindings to cycle between them:
| Parameter | Purpose |
|---|---|
inputConfigFile | Path to input configuration for meta-role bindings |
inputConfigGroup | Input group name within the config file |
nextSubRoleBinding | Input action name for switching to the next sub-role |
subRoles | Array of sub-role names this meta-role can switch between |
Sub-roles are marked with unlisted="True" so they don't appear separately in the role selection interface. Meta-roles can be nested—a sub-role can itself be a meta-role with its own sub-roles, enabling hierarchical role structures.
For end-user documentation on meta-roles, see "Chapter 14. Adding and Editing VR-Engage Entity Models" in the VR-Engage User Guide.
This section covers file organization, deployment patterns, and recommended practices for role configuration.
Role configurations depend on consistent file organization and correct path resolution to load properly across different installations.
Role-related files are organized within the simulation model set directory structure:
Role definitions live in the roles/ directory. Shared configuration modules are grouped in subdirectories such as common/ for general-purpose includes and devices/ for component group files. Input configuration files are stored separately in input/. Entity files that reference roles are located in vrfSim/.
QML overlay files are not stored in the simulation model set. They are located in the data/UI folder within the installation directory, as described in the Overlay configuration section.
The @(vre-roles-dir) macro resolves to the roles directory within the active simulation model set (for example, data/simulationModelSets/VR-Engage/roles/). Use this macro in role file includes and inherits paths to ensure portability across installations.
Avoid using absolute paths in configuration files. Absolute paths break when installations are moved or when configurations are shared between machines.
Before deploying role configurations, verify correct operation:
The VR-Engage log file contains detailed information about role loading, including parameter resolution and component instantiation. Enable verbose logging during development to diagnose configuration issues.
For end-user documentation on available roles, entity configurations, and role selection procedures, see "Chapter 14. Adding and Editing VR-Engage Entity Models" in the VR-Engage User Guide.
Effective role configuration balances reusability, maintainability, and vehicle-specific customization. Following these practices helps create configurations that are easy to understand, modify, and extend.
Maximize reuse through includes: Extract common functionality into shared include files. Radio configurations, action menus, and notification systems typically work identically across multiple roles. Creating shared files for these capabilities reduces duplication and ensures consistent behavior.
Use component groups for related components: Group components that work together into named component groups. This simplifies role definitions and makes it easier to update related components consistently. A "driverControlLogic" group might include the control logic, observer updater, and audio updater that together provide the complete driver experience.
Document all parameters: Every configurable parameter should have a corresponding \vreRoleParam declaration with a clear description. This documentation appears in the generated reference and helps users understand configuration options without examining source code.
Provide sensible defaults: Default parameter values should produce reasonable behavior for typical use cases. Users should only need to override parameters when they want non-standard behavior. Test roles with all defaults to ensure they work correctly out of the box.
Prefer parameter overrides to role duplication: When customizing roles for specific vehicles, use entity-level parameter overrides rather than creating separate role files. This keeps the number of role files manageable and ensures updates to the base role propagate to all vehicles using it.
Test across display configurations: Roles should work correctly with different display layouts. Test with single-monitor, multi-monitor, and VR configurations to ensure overlays position correctly and components handle different rendering scenarios.
See also