Migrating to VR-Forces 4.0.4
This page explains how to migrate from VR-Forces 3.12 to 4.0.4 and also provides the following details about migrating from VR-Forces 4.0.3 to 4.0.4:
Migrating from VR-Forces 3.12 to 4.0.4
The VR-Forces 4.x GUI is built with the VR-Vantage Toolkit, which is significantly different from the VR-Forces 3.12 GUI API. This migration guide describes the major differences between VR-Forces 3.12 and VR-Forces 4.0.4.
Getting Information About Objects
In VR-Forces 3.12 DtModelKey was used to find object information in various dictionaries, most notable the DtModelDataDictionary. In VR-Forces 4.x this has been replaced with DtElementId. The DtElementId is the main key to use to look up data in the system. For details, please see Storing Data.
The API extends the element ID with the scene object ID. The scene object ID ( DtUniqueId) represents an individual screen representation of an object, given a particular model set. For example, the 2D representation of an object has a different scene object ID than the 3D representation. If you have a scene object ID, you can use the DtElementData object to retrieve the element ID based on scene object ID. If you need a scene object ID from an element ID, the DtElementData can also do that mapping.
Selection sets (discussed in Managing Object Selection) contain the DtElementId of the objects selected. You can use these IDs to retrieve information about selected objects.
In VR-Forces 3.12, DtModelData was used as the foundation for data storage, symbol creation, and symbol updating. The DtModelData class does not exist in VR-Forces 4.x. It has been replaced with DtObjectDataInterface. This class (and subclasses) let you access data for any simulated object in the system:
To retrieve information about objects, you can either use the object’s element ID or the object’s name (marking text) from the DtVrfStateViewCollectionManager. The DtVrfStateViewCollectionManager class is analogous to the DtModelDataDictionary in VR-Forces 3.12. In the DtVrfStateViewCollectionManager class you will use the lookupAndCastObjectData() method to return a shared data pointer to the data you need. For example, if you want to find an entity data:
DtEntityDataInterfacePtr data = DtVrfStateViewCollectionManager::instance(myDe).
Also, the IDs in the current selection set can be used to look up data for selected objects.
In VR-Forces 3.12, as soon as an object update was received over the network, it was immediately updated. In VR-Forces 4.x this is not the case. Each object is updated at a certain frame rate. This allows for better performance and control over when object information is updated. For example, if an object is selected, its object update rate is increased, assuming the user might want to know more information about this object. This means all other objects continue to update at a default rate, or not at all. This does not effect the position, speed, or orientation of the object, simply the additional data that is transmitted to the front-end for that object.
This information is stored in DtStateViewCollection classes. Each DtStateViewCollection keeps a list of all particular objects of a state view type and can be used to retrieve information about that object type. So, for example, there are collections of entities, aggregates, and environmental processes.
In VR-Forces the DtVrfStateViewCollectionManager manages all these collections. It is your way of retrieving information about a particular object and its DtStateView information. The DtVrfStateViewCollectionManager is analogous to the VR-Forces 3.12 DtModelDataDictionary class.
In the DtVrfStateViewCollectionManager, all objects that are in the system are stored in the mySimulatedBaseStateViewCollection member. This member holds all structures that are of a DtVrlinkSimulatedBaseState (which all state view objects subclass from). Using the findStateView() methods of the DtVrfStateViewCollectionManager, you can find the basic state view information about any object. This information can be retrieved by marking text name or by DtElementId of the object. If you know that an item is specifically an entity, aggregate, or environmental, you can use the state view collection that is appropriate to find the state data for that object.
The guiObjectDataInterface example details how to use these data interface classes.
Managing Object Selection
In VR-Forces 3.12 you would use the map area of the currently active window to get a list of objects that were currently selected. In VR-Forces 4.x you use the DtSelectionManager class to get the list of object selected, as follows:
DtSelectionManager::IdSet currentSelections = DtSelectionManager::instance(myDe).currentSelection();
You can then iterate over the list to get information about these objects from the DtVrfStateViewCollectionManager:
DtSelectionManager::IdSet::const_iterator iter = currentSelections.begin();
while (iter != currentSelections.end())
DtStateView<DtVrlinkSimulatedEntityState>* stateView =const_cast<DtStateView<DtVrlinkSimulatedEntityState>*>
(DtVrfStateViewCollectionManager::instance(myDe).entityStateView()->findStateView( *iter ) );
VR-Forces 4.x also supplies a convenience class called the DtVrfSelectionHandler. This class has methods for retrieving information about current selections. For example, if you want to get data for all the currently selected objects, you can use the code in the previous example or you could do the following:
std::vector<makVrv::DtSimEntry*> entries = DtVrfSelectionHandler::instance(myDe).getSelectedEntries();
Remember that each DtSimEntry contains the list of all available data for that object. Most objects in VR-Forces have two DtSimEntry views of data: the VR-Link State Repository data (DtVrlinkSimulatedEntityState) and the VR-Forces-specific object data (DtVrfObjectDataState). You can iterate over the simStates() of the state entry, dynamically casting to the object in question that you want. Once the dynamic cast succeeds, you can use that data.
In VR-Forces 3.12 if you wanted to affect the way that symbols were created, you would override the DtMtlSymbolMapper, and install your own version.
In VR-Forces 4.x, symbols are created from DtVisualDefinitionSets. These visualizer sets are organized in DtObjectDictionary classes. Each class of object (entity, aggregate, environmental, interaction) has its own object dictionary. In order to affect the look of a symbol, you can modify the object dictionary, adding your own DtVisualDefinition or DtVisualDefinitionSet. The exampleObjectDictionary, exampleRangeLine and exampleVisualDefinitionSet examples show how this is done.
Mapping entity type enumerations to models is now done in the Entity Type Mappings dialog box rather than in symbol map files. Entity types are mapped to entity definitions that contain the correct visualizer information for that entity type.
In VR-Forces 4.x, the actual visual definitions are not created in the main GUI thread. A DtElement object (or a subclass) is created. It contains all the visualizers needed to visualize an object. DtElement objects are created in the network thread and are protected from the main thread. If you want to, in code, change how these items look, you will need to do that before creation by changing the visual definition set for that particular object. Individual visualizers, however, can be created to self configure given certain conditions. The point being stressed here is that there has been an attempt to move away from direct manipulation of the symbols and move towards a more object oriented approach for symbol manipulation.
If you need to get access to an individual symbol, you can do this through the DtAgentManager. Since each object is scene dependent, you will need to know the model set you are referencing to get the scene object ID of the object you care about:
DtUniqueID idToUse = elementId;
idToUse = ids;
DtAgentUpdateResolverInterface* updater = myDe.agentManager().findUpdater( idToUse );
DtSceneObject* sceneObject =updater->castObjectTypeFromUpdater<DtSceneObject>( "DtSceneObject");
if ( sceneObject )
Please refer to the DtSceneObject class for the information you can retrieve.
Note: The scene objects are screen representations only and do not contain simulation data.
Creating Local (Unpublished) Symbols
In VR-Forces 3.12 you could create unpublished symbols by creating an appropriate DtModelData subclass and adding that model data into the application’s Model Data Dictionary. You would then update that model data and mark it for update in the application to change the symbol.
In VR-Forces 4.x, there is now a DtLocalObjectManager class that does this for you. The guiLocalCreateObject example shows how to use this new class.
In VR-Forces 3.12, in order to affect how a symbol was updated, you would have either subclassed and installed your own version of the DtVrfGuiSymbolUpdater class or added post update callbacks.
In VR-Forces 4.x there is no centralized symbol updater. Each visualizer is responsible for doing its own updating. When a visualizer is created, it is handed a subclass of a DtStateListener. This class contains all the simulation data necessary to drive the visuals of an object. Signals are defined in these state listener subclasses that visualizers can connect to in order to update their state.
If you want to change how an existing object is updating, you must subclass and install that object into the DtVrlinkStateVisualizerFactory if this object has a VR-Link representation, or the DtStateVisualizerFactory if it does not.
To add subclasses to the VR-Link state visualizer factory you must create driver accessories for the VR-Link protocol you want to change. (Please see the addAttr example for an example of how to create an accessory.) You can then reference the VR-Link state visualizer factory as in the slot_onSimCreated() method (in DtAddAttrGuiAccessory.inl):
DtVrlinkStateVisualizerFactory& visualizerStateFactory = DtVrlinkStateVisualizerFactory::instance(
The same methodology can be used for the state visualizer factory:
Sending Messages to the Back-end
In VR-Forces 3.12, to communicate with the back-end (sending sets, tasks or interface content messages), the remote controller was used: DtVrfGuiAppEventController::remoteController().
In VR-Forces 4.x there is no direct access to the remote controller from the GUI thread. Since the GUI is not network dependent, the DtGuiThreadVrfRemoteController class interfaces the GUI to the back-end. Use this class to send all messages. The interface content example and the guiThreadVrfRemoteController example show how to send interface content messages using DtGuiThreadVrfRemoteController.
Adding Callbacks to Receive Messages
In VR-Forces 3.12 the DtVrfMessageInterface class was used to register callback messages for message types. In VR-Forces 4.x the DtNetworkMessageCallbackManager class is used. The DtGuiThreadVrfRemoteController also interfaces with this class, and that can be used as well. The interface content example and the networkCallbackManager example show how to register for a callback message using DtNetworkMessageCallbackManager.
Keyboard and Mouse Handling
In VR-Forces 3.12 you would subclass and install an event handler to handle mouse events and keyboard events. You might also have subclassed and installed your own version of the DtPvdMapArea or connected to signals to handle events.
In VR-Forces 4.x you subclass and install a DtEventProcessor. The DtEventProcessor subclasses have methods for mouse and keyboard messages. If you want to handle a mouse or keyboard message, override the appropriate method (processKeyboardEvent() or processMouseEvent()). If you handle the message you can return true or false. You can also be notified of events that were handled by other event processors before your event processor got a chance, by overriding the above methods and handling the case of a MouseLost event.
Add your event processor subclass into the DtInputDriver class. The DtInputDriver object is referenced through the driver manager:
DtInputDriver& inputDriver = myDe.driverManager().inputDriver();
The event processor can be added to the front or the back of the list (addEventProcessorToFront() or addEventProcessorToBack()). You can also get the list of event processors and insert it directly (eventProcessorList()). The exampleEventProcessor example has an example of how to use an event processor.
Changes to Signal Usage
VR-Forces 3.12 mostly used Qt signals. VR-Forces 4.x mostly uses Boost signals. While some Qt signals are used in the Qt layer, they are usually translated back into Boost signals.
To use a Boost signal you must connect to a signal and give a method to call when the signal is invoked.
The following examples show how to connect to signals without parameters (preTick), and with parameters (postTick). The binding is done to an object class and an instance of that object.
myDe.signal_postTick.connect(boost::bind(&MyObject::method, this, _1));
Note: It is very important to disconnect signals when they are no longer needed or when the object is freed. Failing to disconnect signals can lead to application instability, as, unlike Qt signals, when the object is destroyed the signal is not disconnected.
Application Tick Notification
In VR-Forces 3.12 there was no way to be notified when the application was about to tick or had completed a tick. In VR-Forces 4.x, you can get this information. The main class of a VR-Vantage application is DtDe. The DtDe class is typically passed to any object that might need to use it, and is available to any plug-in on startup.
To be notified when the application is about to tick, connect to the signal_preTick signal.
On a post tick, connect to the signal_postTick signal.
In VR-Forces 3.12, to find out when selections had changed, you would connect to the Qt signal sent by the map area on selection changed (selectionUpdated, selectionChanged, and so on). In VR-Forces 4.x, you use the Selection Manager and its signals to be notified when selections have changed. You can get a reference to the Selection Manager as follows:
DtSelectionManager& selManager = DtSelectionManager::instance(myDe);
The signal_currentSelectionChanged signal is sent any time the current selection is changed. It supplies the following parameters:
The IDs supplied are element IDs, which can be used to retrieve data about the selected objects. Managing Object Selection explains how to use this information.
- The current selection
- What was unselected
- The new selection type
- The old selection type
The signal_vertexSelected and signal_vertexDeselected signals are sent when vertices on a line are selected or unselected.
Tracking New Objects
In VR-Forces 3.12, to find out when an object was added, you would have used the modelDataAdded signal. In VR-Forces 4.x you use the DtElementData object. You can get to the DtElementData as follows:
DtElementData& elementData = myDe.dataBank().elementData();
The signal signal_elementsAdded is sent for any elements added during that tick.
You can then use the State View Collection Manager to find information about the elements added. Due to the nature of the multi-threading of the application, it is possible that the state view data does not yet exist for those elements. In that case, for the state view collection you want to retrieve information for, connect to the signal_stateViewAdded signal. For example:
When the state view is added you can then get information about that object.
Tracking Object Updates
The object data interface allows you to change how often you want to have data refreshed into the object and to be notified when that data is updated. The setUpdateRate() method lets you set the update frequency. The boost signal_dataUpdated signal is sent when data has been updated.
To track resources for entities, you can connect to the signal_resourcesChanged() method of the data interface class and then inspect the resources() method to see the resources. You can request new resources by calling the requestResources() method.
Tracking Object Removals
In VR-Forces 3.12 you would have used the modelDataAboutToBeRemoved signal. In VR-Forces 4.x, you use the element data's signal_elementsToBeRemoved signal. This provides a list of all the elements that are being removed in this tick. Please see Tracking New Objects for how to retrieve a reference to the DtElementData.
You can also track the removal of specific objects. The boost signal_dataRemoved is sent from the data interface when a simulated object is removed.
VR-Forces 4.0.3 to 4.0.4 Simulation Model Set Changes
Changes to the SMS are organized by component or system type:
Flight Command Controllers
Air domain Movement Systems. The flight-command-controller was added to Fixedwing and rotary-wing entities to handle new flight tasks. (For details, please see fixed-WingFlightCommandController.h and rotaryWingFlightCommandController.h.) If you have created your own air domain movement systems, you must add this controller to take advantage of these new tasks and behavior.
The target-priorities parameters have moved. They are no longer part of the target selection controller. They are now in the weapon controllers inside the weapon systems, as follows:
- Target priorities have been removed from the target selection controller (moved into weapons).
- The target-select-controller:weapon-system connections have been removed. The target-selection-controller to sensor connections remain.
- The controller uses DtComponentDescriptor (component-descriptor) for the descriptor type).
- Weapon systems:
- Target priorities have been added into the weapon controllers. The target-selection-criteria parameter has been renamed to targeting-control.
- Target priority metadata has been removed.
- For ballistic weapons, the system:target-list connection is now :target-to-acquire. Please see 125mm-gun.sysdef for an example.
- Missile Weapons. The system:target-list input connection has been removed.
Laser designators have the same changes as weapon systems. They also now have the parameter integrated-with-launcher, which determines how target input works (either from the launcher controller, if integrated, or the target selection controller directly if not). Apache. The laser designator that went along with the laser-guided-hellfire-missile launcher has been moved into the launcher. The laser-guided-hellfire-missile-launcher system has the following changes:
- Uses the new controller integrated-laser-guided-launcher-controller.
- The laser designator that used to be on the entity is now in this system.
- A new connection (connect missile-launcher:target-to-acquire lasercontroller:target-list) was added to represent the missile launcher providing targets to the laser designator.
Emitter systems now defines a radar-mode-list, each one of which defines a beam-list so these can be switched at runtime. For more information, please see Section 7.5, "Configuring Emitters", in VR-Forces Configuration Guide.
In weapon systems the munition-wrapper resource "ammo" has been removed. Individual munitions are now regular resources. Ballistic guns have two changes:
- Burst fire. Some ballistic guns now fire in bursts. The rounds-per-minute and extra-time-between-bursts parameters were added to the ballistic gun controller.
- Magazine-based reloading. The rounds-per-magazine parameter was added for magazine-based reloading.
- Weapon systems. The range-name parameter was added to ballistic weapon actuators and missile launcher controllers. This is the display name for range items associated with this weapon displayed in the GUI.
- Aggregate OPE files. The range-name parameter was added. The combat-rangecontroller was added to define range rings that can represent disaggregation ranges or subordinate weapon systems.
- Munition OPE files. The range-name parameter was added to the missile/torpedo entity definition to display missile range.
Ammo Select Tables
For weapons that fire a burst, hit probability is for the whole burst. New weapons have been added, so if you have made your own damage system, you may have to make a new damage table to add new mappings.
Changes to Support the Fire at Target Task
The new Fire At Target task, which replaces Set Fire Now, required a variety of changes to entity components and interfaces.
Changes to the Weapon Component Interface
The target selection controller (TSC) now communicates with weapon systems through the Weapon Component Interface. Each of the following controllers has a DtWeaponControllerInterface member, which is cached by the TSC:
- DtLasingController (The actual interface is part of the DtLasingControllerWeaponInterfaceInput)
Targets are sent from the TSC to the weapon system through the weapon component interface. The weapon and task (in the case of the Fire At Target task) state is sent back to the TSC.
Changes to the Target Selection Controller
The target selection controller now Derives from DtSingleTaskControllerComponent, so it can process DtFireAtTargetTasks. It now uses DtComponentDescriptor because it does not contain the target-priorities any longer. It responds to weapon list requests from the GUI.
The target selection controller no longer contains target priorities. These are defined in the weapon systems and the TSC gets them through the weapon component interface. The TSC now performs permission to fire checks.
The ports the TSC used to use to communicate to weapons are gone. It still communicates with the sensors through ports.
Changes to Communication
Communication between TSC and turreted weapons now goes through the weapon interface, to the weapon controller - the weapon controller sends the target info to the turret, rather than the turret sending it to the weapon controller.
DtIntegratedLaserGuidedLauncherController is a subclass of the DtLaserGuidedLauncher. It contains 2 new data members:
- DtEntityListOutputPort* myTargetListOutputPort is connected to a laser designator. When it is given a target, it passes along the target to the laser designator.
- DtWeaponComponentInterface myWeaponComponentInterface. Since this launcher is integrated with a laser designator, it can be explicitly tasked.
If this controller is given a new target while it already has a missile in the air, it will ignore the new target and keep its laser designator on the old target until the missile is removed. Then it will go back to processing targets as usual.
Changes to the Lasing Controller
The lasing controller now has a concept of being “integrated” with a launcher. Whether or not it is integrated determines how it gets target input, as follows:
- If integrated, it creates a DtLasingControllerPortInput, which contains an input port through which the launcher controller sends targets.
- If not integrated, it creates a DtLasingControllerWeaponInterfaceInput, which contains a DtWeaponComponentInterface that the TSC finds and sets targets to.
Permission to fire is now handled in the TSC, instead of within the individual weapon controllers.
The OPD Editor no longer adds connections between target selection controllers and weapon systems.
DtSimComponent has a componentFullName for getting the fully qualified name (unique name) for a component.
In the GUI, DtWeaponListRequestor requests a weapon list from the selected entity when the Fire At Target task dialog is opened. It caches the results.
- DtWeaponListRequestAdmin. Sent from the front-end to the back-end to request a weapon list for an entity.
- DtWeaponListResponseAdmin. The response from the back-end with list of weapons for an entity.
- DtFireAtTargetTask. Task to fire upon a target with a specified or automatically chosen weapon.