![]() |
VR-Forces 4.7 Class Documentation
|
Creating or extending components in VR-Forces is explained and demonstrated in a number of examples.
However, when writing components that are intended to be used in a multi-resolution model, there are some additional steps you must take to ensure your model will work in this context.
While the aggregate model is currently the only example of a multi-resolution model in VR-Forces, the guidelines for writing components that are designed to be dynamically enabled and disabled can be applied to any type of simulation object.
Components can exist in two states: enabled or disabled. In the enabled state, the component’s tick() member function is periodically called by the Component Manager. In the disabled state, the tick() function does not get called. The DtSimComponent class has enable() and disable() member functions that can be called to enable or disable a given component. Components are enabled by default.
Similarly, you can enable or disable entire systems of components, by calling DtComponentSystem::enable() or DtComponentSystem::disable().
In the aggregate model, the DtAggregateModelResolutionController is responsible for enabling or disabling the appropriate sets of components and systems. It triggers the switch between models by calling enable() and disable() on the unit’s other components and systems.
Normally, just one task controller component registers to handle a given task type in a simulation object. In a multi-resolution model, there may be more than one. You will want to prepare for the situation in which your task controller is disabled or enabled, due to a switch to another set of components or systems. To accomplish this, you must write your task callback function to take into account the current task state at the time of the switch. When the Task Manager, invokes a task callback, it passes in a DtSimTaskState (simTaskState.h) object, containing the current execution status of the task. The Task Manager manages the handoff of task state between the component being disabled and the newly enabled components. If a task was being executed at the time of an enable/disable transition, the Task Manager obtains a filled-out DtSimTaskState object from the now-disabled task controller and hands it into the newly enabled task controller (as an argument to its task callback). The new task controller can use that DtSimTaskState data to decide how it should initiate its task behavior (that is, start in the middle of the task, instead of the beginning).
There is a DtSimTaskState class for every DtSimTask class that needs one (that is, in cases in which it makes sense to keep track of some intermediate state). For example, the DtWaitTaskState class holds the length of time already executed in the task. The DtPatrolBetweenPointsTaskState class holds the identity of the waypoint the simulation object is moving toward.
To support the transfer of current task state, in your derived task controller you must implement member functions in the following way (declared in taskCtlrCmpnt.h):
Implement a task callback function. It initiates the task behavior for the component. Use data in the incoming DtSimTaskStatePtr to initialize the controller, configuring it to begin executing the task at the appropriate point in its overall execution state (that is, continue along a route, rather than starting over again at the beginning). The prototype for the callback function (in taskCtlrCmpnt.h) is:
In your callback function, dynamically cast the incoming taskState parameter to the expected type. For example, if you have registered a callback for handling DtMoveAlongTasks, then the corresponding task state will be of type DtMoveAlongTaskState. For example,
This discussion assumes that you are writing a task controller component that handles tasks that have some intermediate task state that must be maintained across a transfer between components. However, there are many cases in which this is not necessary. For example, a DtMoveToLocationTask does not have any task state associated with it that needs to be transferred between components. For this task, there is no corresponding DtSimTaskState class. There is no need to implement currentTaskState(). In your task callback, there is no need to use the incoming DtSimTaskStatePtr to initialize the controller with the current task state. (It will point to a base DtSimTaskState object that contains no specific task state data.)
To ensure that your task controller component registers for the appropriate tasks, whenever the component is enabled do the following:
To ensure that your component registers and unregisters for the appropriate set data requests, automatically registering for them when the component gets enabled, and de-registering for them when it gets disabled, do the following:
If you have multiple components that will potentially handle the same DtSetDataRequest, registering and unregistering set data requests in the above hook functions ensures that your component will be able to handle set data requests appropriately, whenever the component gets enabled or disabled. This will avoid the situation in which multiple components simultaneously attempt to handle a given set data request.
[<< Creating a New Controller] [Home] [Top of Page]