Migrating from VR-Forces 3.12 to 4.0.3
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 through 4.0.3.
Also, see Simulation Model Set Changes.
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 the DtStateView. A DtStateView is a template class that takes a DtSimState object as a template. This object is implemented as a subclass, and those subclasses contains the data that represents the information about the object. In VR-Forces 4.x, the main DtSimState objects are:
- DtVrlinkSimulatedBaseState - Information about any VR-Link-based object, such as marking text, type, force
- DtVrlinkSimulatedEntityState - Information about VR-Link entities
- DtVrlinkSimulatedAggregateState - Information about VR-Link aggregates
- DtVrlinkSimulatedEnvironmentProcess - Information about VR-Link environmentals
- DtVrfObjectDataState - Information about an object that is VR-Forces-specific.
When an object is discovered on the network, information about that object from its VR-Link reflected object is placed into the appropriate object state. This state is added to a queue for updating.
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.
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 =
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:
myDe.dataBank().elementData().getSceneObjectIds(elementId, ids, myDe.driverManager().
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.
The scene objects are screen representations only and do not contain simulation data.
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 DtVrfSimMessager class was created to interface the GUI to the back-end. This class should be used to send all messages. The interface content example shows how to send interface content messages using DtVrfSimMessager.
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 DtVrfSimMessageHandler is used. The DtVrfSimMessager also interfaces with this class, and that can be used as well. The interface content example shows how to register for a callback message using DtVrfSimMessageHandler.
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
In VR-Forces 3.12, to be notified when an object was updated, you might have installed your own version of the symbol updater or connected to the model data dictionary’s modelDataUpdated signal. In VR-Forces 4.x you use the state view itself to be notified when state view data is updated.
You first need to find the state view you are interested in:
DtStateView<DtVrlinkSimulatedEntityState>* stateView = const_cast<DtStateView<DtVrlinkSimulatedEntityState>*>(
selHandler.entityStateView()->findStateView( principalSimEntryId ) );
stateView->signal_stateViewUpdated.connect( boost::bind( &MyObject::slot_onPrincipalStateViewUpdated, this, _1));
You will now be notified when that object is updated. This is more efficient than the way it was done in VR-Forces 3.12, because now you can be notified when a very specific instance of the data you are interested in is updated.
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 elements that are being removed in this tick. Please see Tracking New Objects for how to retrieve a reference to the DtElementData.
VR-Forces 3.12.x to 4.0.3 Simulation Model Set Changes
- All OPE and sysdef files have every instance of "tick-period-uses-real-time" set to False by default now instead of True.
- A new general parameter has been added to entities to determine whether they can use the new ground rail movement system (see ground entities movement models below). This parameter looks like the following: (using-rail-movement False)
- Weapon Systems. "target-selection" controllers have an additional parameter in the "target-selection-criteria" as follows: (fire-with-spot-report-only False). The parameter determines whether the target selection controller will fire at an entity automatically or not based on the spot report.
- Movement Models:
- All entity movement systems have an added "preload-terrain-controller" to allow for entities moving in terrains that page data in (such as VR-TheWorld terrains) to page that data in before it gets to the foreseeable un-paged terrain area. Without the controller, entities would page the terrain data in at the time it enters an area where the data has not yet been paged in.
- Systems including the "path-movement" controller have an added parameter that looks like the following: (register-vrf-specific-tasks True)
- Other Systems:
- Systems with "spot-report-generator" now have a "radio-name" field as follows: (radio-name "default")
- Systems with "laser-controller" can be enabled or disabled with the following parameter: (is-enabled True)
- Damage Models. Ground entities have changed their damage tables against "Guided anti-ship missile damage" tables to use the cruise missile damage instead of the standard missile damage. For instance "heavy-armor-vs-missile.dmg" is now "heavy-armor-vs-cruise-missile.dmg"
- Movement Models:
- Ground movement systems have been split into various sysdef files to support multiple movement systems, as follows:
- Vehicles can drive on roads and now use a "combined-movement-system" to switch between them. See "ground-wheels-road.sysdef" and "ground-wheels-road-default.sysdef" and "Technical-Truck_1_1_1_222_27_1_-1_-1.ope".
- Several systems now include the "rail-path-movement" controller if they are to use the road following options as well as a "system-switch-controller" to switch between regular and rail movement systems.
- Disaggregated movement systems have a "convoy-task-controller" necessary for allowing for convoy movement tasks on disaggregated aggregates.
- Counter Measures. Several air entities have counter measures defined in the systems section of their OPE files. It is usually defined in an "other" field and more commonly "other-4". See "US-fighter-air-defense-fixed-wing-platform_1_1_2_225_1_-1_-1_-1.ope".
- Movement. "flight-kinematics" actuator now has an added parameter for a drag coefficient defined as follows: (drag-coefficient 0.100000)
- Several entities now have a "contact-fusion" controller to tie in several sensor systems into a single place. These controllers have associated connections to connect the sensor ports to the contact-fusion controller for entity detection. New lifeforms should use the "contact-fusion" controller.
- Several entities now have a "target-selection" controller much like other entities. These controllers have associated connections to connect the target selection controller. New lifeform entities should use the "target-selection" controller.
- Movement. All movement systems for lifeforms have removed the "human-patrol" controller.