-
Notifications
You must be signed in to change notification settings - Fork 77
Ardor3D Interact System
The Interact System in Ardor3D provides in-scene widgets for manipulating the 3D environment. Out of the box, these widgets provide functionality for scaling, rotating, and translating scenegraph objects in a variety of ways. Custom widgets can be added as well, allowing for any user-desired functionality.
Acting as the core element of the Interact System, the InteractManager class is responsible for holding references to available widgets, keeping track of the active widget, appropriately passing user input to the widgets and rendering and updating widgets.
Generally speaking, most applications do best with a singleton instance of InteractManager. Even applications using multiple 3D views will likely benefit with having a single InteractManager as this keeps current the widget consistent for the user, similar to how in Gimp or PhotoShop you stay in your current tool (pencil, paint, fill, and so forth), regardless of how you might switch between the image windows.
After constructing the manager, decide how to route input from the canvas. A typical case may involve first sending input to the manager's LogicalLayer, then sending any unhandled input through to another LogicalLayer managing the camera or other scene controls. InteractManager has a convenience method called setupInput(...)
that does exactly this.
In more complex situations, particularly in multi-canvas applications, you may need to manage input flow more directly.
Widgets consist of a handle containing visualization and need to be told how that handle should be renderer and the logic on what to do if we mouse over or drag on that visualization. Therefore, making your own widget type involves extending AbstractInteractWidget
and attaching scenegraph elements to the _handle Node and then overriding processInput(...)
and render(...)
to provide appropriate logic. We may also wish to react to a change in the target we are working with by overriding targetDataUpdated(...)
.
As an example, MoveWidget is a built-in Ardor3D widget providing single or multi-axis translation. Constructing the widget involves instantiating it and then using withAxis methods to pick the X, Y, and or Z axes to enable. These methods create an appropriately rotated Ardor3D Arrow shape and attach it to the handle. In render, the widget looks to see if the InteractManager has a target Spatial it is interacting with, and if so, moves the handle to that Spatial and renders it. When the target changes, the widget may update its handle's rotation to match the target such that the axes point along the local axes of the target. It also updates its handle's scale to match the bounding volume of the target (if one is set.) Finally, the MoveWidget overrides processInput to check and react to mouse drags by detecting the mouse movement along the appropriate plane based on the arrow the user is dragging.
Widgets are added and removed via the manager's addWidget(...)
and removeWidget(...)
methods. A manager may only have one active widget at a time, set via setActiveWidget(...)
. These methods all take a widget instance parameter; therefore, it may be handy to hold your references in fields or a Map of some sort. The logic of when to set a particular widget as active is up to the application.
It is often useful to impose constraints or do other sanity checks on operations performed by widgets. The Interact System provides a mechanism to do this via the UpdateFilter
interface. Examples of filters included in Ardor3D include:
- AllowScaleFilter: enables or disables scaling on specific axes.
- MinMaxScaleFilter: clamps the target Spatial's scale to a given range.
- PlaneBoundaryFilter: forces the target Spatial to stay on the positive side of a given Plane.
Filters are added and removed via the manager's addFilter(...)
and removeFilter(...)
methods. The manager calls their applyFilter(...)
method whenever a widget receives input and marks that input as "consumed." The manager also provides filters a chance to interject behavior before and after mouse drags.