# JME3 Cinematics

JME3 cinematics (com.jme.cinematic) allow you to remote control nodes and cameras in a 3D game: You can script and and play cinematic scenes. Combined with screen recording software, you use cinematics to create
and movies/trailers of your game. Internally, Cinematics are implemented as AppStates.

Short overview of the cinematic process:

1. Plan the script of your movie.
   Write down a timeline (e.g. on paper) of which character should be at which spot at which time.
2. Attach the scene objects that you want to remote-control to one Node.
   This Node can be the rootNode, or a Node that is attached to the rootNode.
3. Create a Cinematic object for this movie scene. The Cinematic will contain and manage the movie script.
4. For each line in your script (for each frame in your timeline), add a CinematicEvent to the Cinematic.

## Sample Code

## How to Use a Cinematic

A Cinematic is like a movie script for a node.

    Cinematic cinematic = new Cinematic(sceneNode, duration);
    cinematic.addCinematicEvent(starttime1, track1);
    cinematic.addCinematicEvent(starttime2, track2);
    cinematic.addCinematicEvent(starttime2, track3);
    ...
    stateManager.attach(cinematic);

1. Create one Cinematic per scripted scene.
   - `sceneNode` is the node containing the scene (can be the rootNode).
   - `duration` is the duration of the whole scene in seconds.
   - Each Cinematic is a set of CinematicEvents, that are triggered at a given moment on the timeline.
2. Create one CinematicEvent for each line of your movie script.
   - `track` is one motion of a moving object. You can add several tracks. More details below.
   - `starttime` is the time when this particular cinematic event starts on the timeline. Specify the start time in seconds since the beginning of the cinematic.
3. Attach the Cinematic to the SimpleApplication's stateManager.
4. Play, stop and pause the Cinematic from your code.

Method | Usage
--- | ---
cinematic.play() | Starts playing the cinematic from the start, or from where it was paused.
cinematic.stop() | Stops playing the cinematic and rewinds it.
cinematic.pause() | Pauses the cinematic.

## Tracks (CinematicEvents)

Just like a movie script consists of lines with instructions to the actors, each Cinematic consists of a series of tracks.

Here is the list of available CinematicEvents that you use as tracks. Each track remote-controls scene objects in a different way:

Tracks (CinematicEvents) | Description
--- | ---
MotionTrack | Use a MotionTrack to move a Spatial non-linearly over time. A MotionTrack is based on a list of waypoints in a MotionPath. The curve goes through each waypoint, and you can adjust the tension of the curve to modify the roundedness of the path. This is the motion interpolation you are going to use in most cases.
PositionTrack | Use a PositionTrack to move a Spatial linearly over time. This linear interpolation results in straight motion segments between the way points. Use this to make the remote-controlled objects zig-zag from one way point to the other in a straight line.
RotationTrack | Use a RotationTrack to change the rotation of a Spatial over time. It spins the Spatial to the given angle in the given amount of time by linearly interpolating the rotation.
ScaleTrack | Use a ScaleTrack to change the size of a Spatial over time. It resizes the Spatial in the given amount of time by linearly interpolating the scale.
SoundTrack | Use a SoundTrack to play a sound at a given time for the given duration.
GuiTrack | Displays a Nifty GUI at a given time for the given duration. Use it to display subtitles or HUD elements. Bind the Nifty GUI XML to the cinematic using `cinematic.bindUi("path/to/nifty/file.xml");`
AnimationTrack | Use this to start playing a model animation at a given time (a character walking animation for example)

The jMonkey team can add more types of tracks, just ask in the forum.

### MotionTrack

A MotionTrack moves a Spatial along a complex path.

    MotionTrack track = new MotionTrack(thingNode, path);

Details of the constructor:

- `thingNode` is the Spatial to be moved.
- `path` is a complex MotionPath.

To create a MotionTrack, do the following:

1. Create a MotionPath
2. Create a MotionTrack based on the MotionPath.
3. Configure your MotionTrack (see below).
4. Add the MotionTrack to a Cinematic.

MotionTrack configuration method | Usage
--- | ---
track.setLoopMode(LoopMode.Loop) | Sets whether the animation along this path should loop (LoopMode.Loop) or play only once (LoopMode.DontLoop).
track.setDirectionType(MotionTrack.Direction.None) | Sets the direction behavior type of the controled node. Direction.None deactivates this feature. You can choose from the following options: LookAt, Path, PathAndRotation, Rotation.
track.setDirectionType(MotionTrack.Direction.LookAt) | The spatial turns (rotates) to keep facing a certain point while moving. Specify the point with the `setLookAt()` method.
track.setDirectionType(MotionTrack.Direction.Path) | The spatial always faces in the direction of the path while moving.
track.setDirectionType(MotionTrack.Direction.PathAndRotation) | The spatial faces the direction of the path, plus an added rotation. Use together with the `setRotation()` method.
track.setDirectionType(MotionTrack.Direction.Rotation) | The spatial spins (rotates) while moving. You describe the spin by a custom quaternion. Use together with the `setRotation()` method.
track.setLookAt(teapot.getWorldTranslation(), Vector3f.UNIT_Y) | The spatial always faces towards this location. Use together with `MotionTrack.Direction.LookAt`.
track.setRotation(quaternion) | Sets the rotation. Use together with `MotionTrack.Direction.Rotation` or `MotionTrack.Direction.PathAndRotation`.

Tip: Most likely you remote-control more than one object in your scene. Give the tracks and paths useful names such as `dragon_track`, `dragon_path`, `hero_track`, `hero_path`, etc.

### PositionTrack

A PositionTrack moves a Spatial in a straight line from its current position to the end position.

    PositionTrack track = new PositionTrack(
        thingNode, endPosition, duration, loopMode);

Details of the constructor:

- `thingNode` is the Spatial to be moved.
- `endPosition` is the target location as Vector3f.
- `duration` is the time that it should take from start to end point.
- `loopMode` can be LoopMode.Loop, LoopMode.DontLoop, LoopMode.Cycle.

The start location is always the current location of the Spatial.

### RotationTrack

A RotationTrack remote-controls the rotation of a spatial.

    RotationTrack thingRotationControl = new RotationTrack(
        thingNode, endRotation,  duration, loopMode);

Details of the constructor:

- `thingNode` is the Spatial to be rotated.
- `endRotation` is the target rotation in Quaternion format.
- `duration` is the time that it should take from start to target rotation.
- `loopMode` can be LoopMode.Loop, LoopMode.DontLoop, LoopMode.Cycle.

### ScaleTrack

A ScaleTrack remote-controls whether a spatial grows or shrinks.

    ScaleTrack thingScaleControl = new ScaleTrack(
        thingNode, endScale,  duration, loopMode);

Details of the constructor:

- `thingNode` is the Spatial to be resized.
- `endScale` is the target Scale in Vector3f format.
- `duration` is the time that it should take from start to target scale.
- `loopMode` can be LoopMode.Loop, LoopMode.DontLoop, LoopMode.Cycle.

### SoundTrack

A SoundTrack plays a sound as part of the cinematic.

    SoundTrack( audioPath, isStream, duration, loopMode )

Details of the constructor:

- `audioPath` is the path to an audio file as String, e.g. "Sounds/mySound.wav".
- `isStream` toggles between streaming and buffering. Set to true to stream long audio file, set to false to play short buffered sounds.
- `duration` is the time that it should take to play.
- `loopMode` can be LoopMode.Loop, LoopMode.DontLoop, LoopMode.Cycle.

### GuiTrack

A GuiTrack shows or hide a NiftyGUI as part of a cinematic.

    GuiTrack( screen, duration, loopMode )

You must use this together with bindUI() to specify the Nifty GUI XML file that you want to load:

    cinematic.bindUi("Interface/subtitle.xml");

Details of the constructor:

- `screen` is the name of the Nifty GUI screen to load, as String.
- `duration` is the time that it should take to play.
- `loopMode` can be LoopMode.Loop, LoopMode.DontLoop, LoopMode.Cycle.

### AnimationTrack

An AnimationTrack triggers an animation as part of a cinematic.

    AnimationTrack( thingNode, animationName, duration, loopMode )

Details of the constructor:

- `thingNode` is the Spatial whose animation you want to play.
- `animationName` the name of the animation stored in the animated model that you want to trigger, as a String.
- `duration` is the time that it should take to play.
- `loopMode` can be LoopMode.Loop, LoopMode.DontLoop, LoopMode.Cycle.

### Customizations

You can extend individual CinematicEvents. The
shows how to extend a GuiTrack to script subtitles. See how the subtitles are used in the
.

You can also create new CinematicEvent by extending
. An AbstractCinematicEvent implements the CinematicEvent interface and provides duration, time, speed, etc??? management. Look at the
is to use this for a custom fadeIn/fadeOut effect in combination with a com.jme3.post.filters.FadeFilter.

## Interacting with Cinematics

### CinematicEventListener

    CinematicEventListener cel = new CinematicEventListener() {
      public void onPlay(CinematicEvent cinematic) {
        chaseCam.setEnabled(false);
        System.out.println("play");
      }

      public void onPause(CinematicEvent cinematic) {
        chaseCam.setEnabled(true);
        System.out.println("pause");
      }

      public void onStop(CinematicEvent cinematic) {
        chaseCam.setEnabled(true);
        System.out.println("stop");
      }
    }
    cinematic.addListener(cel);

### Physics Interaction

Upcoming.

## More Information

See also:

view online version