Additional features of AcorusDemo
TestAcorusDemo is a test application
that demonstrates more built-in features of AcorusDemo
:
-
display text on a solid background using an overlay
-
add world axes to a scene and toggle their visibility
-
pause animations and physics without disabling camera motion
-
scale a model to a specified height
-
translate a 3-D model so it rests on the X-Z plane, with its center on the Y axis
-
select among possible values, as in a menu
-
store materials in a "library" and retrieve them by name
Display text on a solid background
An overlay is a rounded rectangle with a solid background color, used to display multiple lines of text.
The concrete Overlay
class is a subtype of BaseAppState
and inherits its life-cycle hooks:
+ stateAttached(AppStateManager)
+ update(float)
+ render(RenderManager)
+ postRender()
+ stateDetached(AppStateManager)
Unlike most appstates, overlays are initially disabled. So at a minimum, you need to instantiate the overlay, attach it to your application, and enable it:
Overlay overlay = new Overlay(idString, widthPixels, numStatusLines);
stateManager.attach(overlay);
overlay.setEnabled(true);
Be default, overlays are set in from the upper-left corner of the GUI viewport.
However, you can alter the location policy
using overlay.setLocationPolicy(newPolicy)
.
If the policy is anything other than LowerLeft
and the viewport is resizable,
you should ensure the overlay’s location gets updated on every resize:
@Override
public void onViewPortResize(int newWidth, int newHeight) {
super.onViewPortResize(newWidth, newHeight);
overlay.onViewPortResize(newWidth, newHeight);
}
By default, overlay text is white and left-aligned on a black background. However, you can alter these properties:
overlay.setColor(lineIndex, textColor);
overlay.setAlignmentAll(globalAlignment);
overlay.setAlignment(lineIndex, alignment2);
overlay.setBackgroundColor(newColor);
World axes
The world axes are 3 arrows (red for +X, green for +Y, and blue for +Z) whose tails spring from the world origin (0,0,0).
By default, the axes are invisible. However, it’s often helpful to visualize these axes — during a demo, for instance, or while debugging.
AcorusDemo
lays the groundwork so that an application can easily bind a hotkey
that empowers the user to toggle visibility of the axes:
@Override
public void moreDefaultBindings() {
InputMode dim = getDefaultInputMode();
dim.bind(asToggleWorldAxes, KeyInput.KEY_SPACE);
}
Pausing animations
During a demo (or while debugging) one often wants
to pause the action for close examination.
SimpleApplication
provides a setSpeed()
interface
to alter the global speed of the application.
However, setting the speed to zero
not only pauses animations, cinematics, and physics;
it also freezes camera motion.
AcorusDemo
lays the groundwork so that an application can easily bind a hotkey
that empowers the user to pause animations (and cinematics and physics)
without affecting the built-in FlyByCamera
:
@Override
public void moreDefaultBindings() {
InputMode dim = getDefaultInputMode();
dim.bind(asTogglePause, KeyInput.KEY_PAUSE);
}
Scaling and centering a 3-D model
AcorusDemo
provides a static setCgmHeight()
method
that scales a 3-D model to a specified height.
The model’s height is calculated
from the minimal axis-aligned bounding box (AABB) containing its mesh vertices.
AcorusDemo
also provides a static centerCgm()
method
that translates a 3-D model
so the center of its base rectangle lies at the world origin.
The base rectangle is calculated
from the minimal AABB containing its mesh vertices.
Used together, these methods facilitate display of 3-D models without needing to know their coordinates and/or dimensions in advance:
setCgmHeight(model, 2f); // Make the model 2 world units tall.
centerCgm(model); // Position it above the origin.
Selecting among values
In lieu of mouse-driven menu widgets,
AcorusDemo
provides a framework for empowering users
to interactively select a value from an array of possible values.
The selected value can be displayed in an Overlay
that’s updated for every frame:
@Override
public void simpleUpdate(float tpf) {
super.simpleUpdate(tpf);
statusOverlay.setText(0, selectedValue);
and hotkeys can be bound to actions that cycle through the possible values:
public void moreDefaultBindings() {
InputMode dim = getDefaultInputMode();
dim.bind("next value", KeyInput.KEY_NUMPAD6);
dim.bind("previous value", KeyInput.KEY_NUMPAD4);
@Override
public void onAction(String actionString, boolean ongoing, float tpf) {
if (ongoing) {
switch (actionString) {
case "next value":
// Select the next value in the array.
selectedValue = advanceString(valueArray, selectedValue, +1);
composer.setCurrentAction(clipName);
return;
case "previous value":
// Select the previous name in the array.
selectedValue = advanceString(valueArray, selectedValue, -1);
composer.setCurrentAction(clipName);
return;
Analogous with advanceString()
,
methods are also provided to select among float
and int
values.
A library of materials
JMonkeyEngine has a built-in mechanism to assign names to materials. Acorus goes one step further, implementing a material library that makes it easy to access materials by name.
To add a material to the library, invoke the registerMaterial()
method.
To access a material by name, invoke the findMaterial()
method.
During startup, Acorus invokes the generateMaterials()
method
to initialize the library.
Applications may override this method, if desired.