Cinematics :

- One can now shift time forward an backward in a cinematic with the setTime(float) method, all sub cinematic events support it except soundtrack (has to be implemented)
- Enhanced MotionPath calculation to allow time shifting, and made speed more constant
- changed test cases accordingly
- some more javadoc
- fixed some problems in GUITrack


git-svn-id: https://jmonkeyengine.googlecode.com/svn/trunk@8913 75d07b2b-3a1a-0410-a2c5-0572b91ccdca
3.0
rem..om 13 years ago
parent 6152155c61
commit 08af19ec5b
  1. 89
      engine/src/core/com/jme3/cinematic/Cinematic.java
  2. 74
      engine/src/core/com/jme3/cinematic/MotionPath.java
  3. 4
      engine/src/core/com/jme3/cinematic/TimeLine.java
  4. 19
      engine/src/core/com/jme3/cinematic/events/AbstractCinematicEvent.java
  5. 21
      engine/src/core/com/jme3/cinematic/events/AnimationTrack.java
  6. 30
      engine/src/core/com/jme3/cinematic/events/CinematicEvent.java
  7. 44
      engine/src/core/com/jme3/cinematic/events/MotionTrack.java
  8. 6
      engine/src/core/com/jme3/cinematic/events/SoundTrack.java
  9. 7
      engine/src/core/com/jme3/post/filters/FadeFilter.java
  10. 12
      engine/src/niftygui/com/jme3/cinematic/events/GuiTrack.java
  11. 156
      engine/src/test/jme3test/animation/TestCinematic.java
  12. 2
      engine/src/test/jme3test/animation/TestMotionPath.java
  13. 6
      engine/test-data/Interface/Nifty/CinematicTest.xml

@ -37,11 +37,13 @@ import com.jme3.app.state.AppState;
import com.jme3.app.state.AppStateManager; import com.jme3.app.state.AppStateManager;
import com.jme3.cinematic.events.AbstractCinematicEvent; import com.jme3.cinematic.events.AbstractCinematicEvent;
import com.jme3.cinematic.events.CinematicEvent; import com.jme3.cinematic.events.CinematicEvent;
import com.jme3.cinematic.events.CinematicEventListener;
import com.jme3.export.*; import com.jme3.export.*;
import com.jme3.renderer.Camera; import com.jme3.renderer.Camera;
import com.jme3.renderer.RenderManager; import com.jme3.renderer.RenderManager;
import com.jme3.scene.CameraNode; import com.jme3.scene.CameraNode;
import com.jme3.scene.Node; import com.jme3.scene.Node;
import com.jme3.scene.control.CameraControl;
import com.jme3.scene.control.CameraControl.ControlDirection; import com.jme3.scene.control.CameraControl.ControlDirection;
import java.io.IOException; import java.io.IOException;
import java.util.ArrayList; import java.util.ArrayList;
@ -58,7 +60,6 @@ import java.util.logging.Logger;
public class Cinematic extends AbstractCinematicEvent implements AppState { public class Cinematic extends AbstractCinematicEvent implements AppState {
private static final Logger logger = Logger.getLogger(Application.class.getName()); private static final Logger logger = Logger.getLogger(Application.class.getName());
private String niftyXmlPath = null;
private Node scene; private Node scene;
protected TimeLine timeLine = new TimeLine(); protected TimeLine timeLine = new TimeLine();
private int lastFetchedKeyFrame = -1; private int lastFetchedKeyFrame = -1;
@ -66,8 +67,8 @@ public class Cinematic extends AbstractCinematicEvent implements AppState {
private Map<String, CameraNode> cameras = new HashMap<String, CameraNode>(); private Map<String, CameraNode> cameras = new HashMap<String, CameraNode>();
private CameraNode currentCam; private CameraNode currentCam;
private boolean initialized = false; private boolean initialized = false;
// private Nifty nifty = null;
private Map<String, Map<String, Object>> eventsData; private Map<String, Map<String, Object>> eventsData;
private int scheduledPause = -1;
public Cinematic() { public Cinematic() {
} }
@ -94,7 +95,8 @@ public class Cinematic extends AbstractCinematicEvent implements AppState {
@Override @Override
public void onPlay() { public void onPlay() {
if (isInitialized()) { if (isInitialized()) {
enableCurrentCam(true); scheduledPause = -1;
//enableCurrentCam(true);
if (playState == PlayState.Paused) { if (playState == PlayState.Paused) {
for (int i = 0; i < cinematicEvents.size(); i++) { for (int i = 0; i < cinematicEvents.size(); i++) {
CinematicEvent ce = cinematicEvents.get(i); CinematicEvent ce = cinematicEvents.get(i);
@ -125,7 +127,6 @@ public class Cinematic extends AbstractCinematicEvent implements AppState {
ce.pause(); ce.pause();
} }
} }
enableCurrentCam(false);
} }
@Override @Override
@ -136,8 +137,6 @@ public class Cinematic extends AbstractCinematicEvent implements AppState {
oc.writeSavableArrayList((ArrayList) cinematicEvents, "cinematicEvents", null); oc.writeSavableArrayList((ArrayList) cinematicEvents, "cinematicEvents", null);
oc.writeStringSavableMap(cameras, "cameras", null); oc.writeStringSavableMap(cameras, "cameras", null);
oc.write(timeLine, "timeLine", null); oc.write(timeLine, "timeLine", null);
oc.write(niftyXmlPath, "niftyXmlPath", null);
} }
@ -149,12 +148,6 @@ public class Cinematic extends AbstractCinematicEvent implements AppState {
cinematicEvents = ic.readSavableArrayList("cinematicEvents", null); cinematicEvents = ic.readSavableArrayList("cinematicEvents", null);
cameras = (Map<String, CameraNode>) ic.readStringSavableMap("cameras", null); cameras = (Map<String, CameraNode>) ic.readStringSavableMap("cameras", null);
timeLine = (TimeLine) ic.readSavable("timeLine", null); timeLine = (TimeLine) ic.readSavable("timeLine", null);
niftyXmlPath = ic.readString("niftyXmlPath", null);
}
public void bindUi(String xmlPath) {
niftyXmlPath = xmlPath;
} }
@Override @Override
@ -169,22 +162,11 @@ public class Cinematic extends AbstractCinematicEvent implements AppState {
} }
public void initialize(AppStateManager stateManager, Application app) { public void initialize(AppStateManager stateManager, Application app) {
if (niftyXmlPath != null) {
// NiftyJmeDisplay niftyDisplay = new NiftyJmeDisplay(app.getAssetManager(),
// app.getInputManager(),
// app.getAudioRenderer(),
// app.getGuiViewPort());
// nifty = niftyDisplay.getNifty();
// nifty.fromXmlWithoutStartScreen(niftyXmlPath);
// app.getGuiViewPort().addProcessor(niftyDisplay);
}
initEvent(app, this); initEvent(app, this);
for (CinematicEvent cinematicEvent : cinematicEvents) { for (CinematicEvent cinematicEvent : cinematicEvents) {
cinematicEvent.initEvent(app, this); cinematicEvent.initEvent(app, this);
} }
initialized = true; initialized = true;
} }
@ -215,8 +197,22 @@ public class Cinematic extends AbstractCinematicEvent implements AppState {
} }
} }
private void step() {
if (playState != PlayState.Playing) {
play();
scheduledPause = 2;
}
}
@Override @Override
public void onUpdate(float tpf) { public void onUpdate(float tpf) {
if (scheduledPause >= 0) {
if (scheduledPause == 0) {
pause();
}
scheduledPause--;
}
for (int i = 0; i < cinematicEvents.size(); i++) { for (int i = 0; i < cinematicEvents.size(); i++) {
CinematicEvent ce = cinematicEvents.get(i); CinematicEvent ce = cinematicEvents.get(i);
ce.internalUpdate(tpf); ce.internalUpdate(tpf);
@ -235,6 +231,28 @@ public class Cinematic extends AbstractCinematicEvent implements AppState {
lastFetchedKeyFrame = keyFrameIndex; lastFetchedKeyFrame = keyFrameIndex;
} }
@Override
public void setTime(float time) {
super.setTime(time);
int keyFrameIndex = timeLine.getKeyFrameIndexFromTime(time);
//triggering all the event from start to "time"
//then computing timeOffset for each event
for (int i = 0; i <= keyFrameIndex; i++) {
KeyFrame keyFrame = timeLine.get(i);
if (keyFrame != null) {
for (CinematicEvent ce : keyFrame.getCinematicEvents()) {
if (playState == PlayState.Playing) {
ce.play();
}
ce.setTime(time - timeLine.getKeyFrameTime(keyFrame));
}
}
}
step();
}
public KeyFrame addCinematicEvent(float timeStamp, CinematicEvent cinematicEvent) { public KeyFrame addCinematicEvent(float timeStamp, CinematicEvent cinematicEvent) {
KeyFrame keyFrame = timeLine.getKeyFrameAtTime(timeStamp); KeyFrame keyFrame = timeLine.getKeyFrameAtTime(timeStamp);
if (keyFrame == null) { if (keyFrame == null) {
@ -255,6 +273,9 @@ public class Cinematic extends AbstractCinematicEvent implements AppState {
public void cleanup() { public void cleanup() {
} }
/**
* fits the duration of the cinamatic to the duration of all its child cinematic events
*/
public void fitDuration() { public void fitDuration() {
KeyFrame kf = timeLine.getKeyFrameAtTime(timeLine.getLastKeyFrameIndex()); KeyFrame kf = timeLine.getKeyFrameAtTime(timeLine.getLastKeyFrameIndex());
float d = 0; float d = 0;
@ -271,7 +292,7 @@ public class Cinematic extends AbstractCinematicEvent implements AppState {
public CameraNode bindCamera(String cameraName, Camera cam) { public CameraNode bindCamera(String cameraName, Camera cam) {
CameraNode node = new CameraNode(cameraName, cam); CameraNode node = new CameraNode(cameraName, cam);
node.setControlDir(ControlDirection.SpatialToCamera); node.setControlDir(ControlDirection.SpatialToCamera);
node.getControl(0).setEnabled(false); node.getControl(CameraControl.class).setEnabled(false);
cameras.put(cameraName, node); cameras.put(cameraName, node);
scene.attachChild(node); scene.attachChild(node);
return node; return node;
@ -283,7 +304,7 @@ public class Cinematic extends AbstractCinematicEvent implements AppState {
private void enableCurrentCam(boolean enabled) { private void enableCurrentCam(boolean enabled) {
if (currentCam != null) { if (currentCam != null) {
currentCam.getControl(0).setEnabled(enabled); currentCam.getControl(CameraControl.class).setEnabled(enabled);
} }
} }
@ -296,13 +317,18 @@ public class Cinematic extends AbstractCinematicEvent implements AppState {
enableCurrentCam(true); enableCurrentCam(true);
} }
public void activateCamera(float timeStamp, final String cameraName) { public void activateCamera(final float timeStamp, final String cameraName) {
addCinematicEvent(timeStamp, new AbstractCinematicEvent() { addCinematicEvent(timeStamp, new AbstractCinematicEvent() {
@Override
public void play() {
super.play();
stop();
}
@Override @Override
public void onPlay() { public void onPlay() {
setActiveCamera(cameraName); setActiveCamera(cameraName);
stop();
} }
@Override @Override
@ -316,6 +342,11 @@ public class Cinematic extends AbstractCinematicEvent implements AppState {
@Override @Override
public void onPause() { public void onPause() {
} }
@Override
public void setTime(float time) {
play();
}
}); });
} }
@ -323,10 +354,6 @@ public class Cinematic extends AbstractCinematicEvent implements AppState {
this.scene = scene; this.scene = scene;
} }
// public Nifty getNifty() {
// return nifty;
// }
private Map<String, Map<String, Object>> getEventsData() { private Map<String, Map<String, Object>> getEventsData() {
if (eventsData == null) { if (eventsData == null) {
eventsData = new HashMap<String, Map<String, Object>>(); eventsData = new HashMap<String, Map<String, Object>>();

@ -38,6 +38,7 @@ import com.jme3.material.Material;
import com.jme3.math.ColorRGBA; import com.jme3.math.ColorRGBA;
import com.jme3.math.Spline; import com.jme3.math.Spline;
import com.jme3.math.Spline.SplineType; import com.jme3.math.Spline.SplineType;
import com.jme3.math.Vector2f;
import com.jme3.math.Vector3f; import com.jme3.math.Vector3f;
import com.jme3.scene.Geometry; import com.jme3.scene.Geometry;
import com.jme3.scene.Node; import com.jme3.scene.Node;
@ -68,39 +69,60 @@ public class MotionPath implements Savable {
} }
/** /**
* interpolate the path giving the tpf and the motionControl * interpolate the path giving the time since the beginnin and the motionControl
* this methods sets the new localTranslation to the spatial of the motionTrack control. * this methods sets the new localTranslation to the spatial of the motionTrack control.
* @param tpf * @param time the time since the animation started
* @param control * @param control the ocntrol over the moving spatial
*/ */
public void interpolatePath(float tpf, MotionTrack control) { public float interpolatePath(float time, MotionTrack control) {
float val; float val;
float traveledDistance = 0;
TempVars vars = TempVars.get(); TempVars vars = TempVars.get();
Vector3f temp = vars.vect1; Vector3f temp = vars.vect1;
Vector3f tmpVector = vars.vect2; Vector3f tmpVector = vars.vect2;
switch (spline.getType()) { switch (spline.getType()) {
case CatmullRom: case CatmullRom:
val = tpf * (spline.getTotalLength() / control.getDuration()); //this iterative process is done to keep the spatial travel at a constant speed on the path even if
//waypoints are not equally spread over the path
// we compute the theorical distance that the spatial should travel on this frame
val = (time * (spline.getTotalLength() / control.getDuration())) - control.getTraveledDistance();
//adding and epsilon value to the control currents value
control.setCurrentValue(control.getCurrentValue() + eps); control.setCurrentValue(control.getCurrentValue() + eps);
//computing the new position at current value
spline.interpolate(control.getCurrentValue(), control.getCurrentWayPoint(), temp); spline.interpolate(control.getCurrentValue(), control.getCurrentWayPoint(), temp);
//computing traveled distance at current value
float dist = getDist(control, temp, tmpVector); float dist = getDist(control, temp, tmpVector);
//While the distance traveled this frame is below the theorical distance we iterate the obove computation
while (dist < val) { while (dist < val) {
//storing the distance traveled this frame
traveledDistance = dist;
control.setCurrentValue(control.getCurrentValue() + eps); control.setCurrentValue(control.getCurrentValue() + eps);
spline.interpolate(control.getCurrentValue(), control.getCurrentWayPoint(), temp); spline.interpolate(control.getCurrentValue(), control.getCurrentWayPoint(), temp);
dist = getDist(control, temp, tmpVector); dist = getDist(control, temp, tmpVector);
} }
//compute the direction of the spline
if (control.needsDirection()) { if (control.needsDirection()) {
tmpVector.set(temp); tmpVector.set(temp);
control.setDirection(tmpVector.subtractLocal(control.getSpatial().getLocalTranslation()).normalizeLocal()); control.setDirection(tmpVector.subtractLocal(control.getSpatial().getLocalTranslation()).normalizeLocal());
} }
//updating traveled distance to the total distance traveled by the spatial since the start
traveledDistance += control.getTraveledDistance();
break; break;
case Linear: case Linear:
val = control.getDuration() * spline.getSegmentsLength().get(control.getCurrentWayPoint()) / spline.getTotalLength(); //distance traveled this frame
control.setCurrentValue(Math.min(control.getCurrentValue() + tpf / val, 1.0f)); val = (time * (spline.getTotalLength() / control.getDuration())) - control.getTraveledDistance();
// computing total traveled distance
traveledDistance = control.getTraveledDistance() + val;
//computing interpolation ratio for this frame
val = val / spline.getSegmentsLength().get(control.getCurrentWayPoint());
control.setCurrentValue(Math.min(control.getCurrentValue() + val, 1.0f));
//interpolationg position
spline.interpolate(control.getCurrentValue(), control.getCurrentWayPoint(), temp); spline.interpolate(control.getCurrentValue(), control.getCurrentWayPoint(), temp);
//computing line direction
if (control.needsDirection()) { if (control.needsDirection()) {
tmpVector.set(spline.getControlPoints().get(control.getCurrentWayPoint() + 1)); tmpVector.set(spline.getControlPoints().get(control.getCurrentWayPoint() + 1));
control.setDirection(tmpVector.subtractLocal(spline.getControlPoints().get(control.getCurrentWayPoint())).normalizeLocal()); control.setDirection(tmpVector.subtractLocal(spline.getControlPoints().get(control.getCurrentWayPoint())).normalizeLocal());
@ -111,11 +133,19 @@ public class MotionPath implements Savable {
} }
control.getSpatial().setLocalTranslation(temp); control.getSpatial().setLocalTranslation(temp);
vars.release(); vars.release();
return traveledDistance;
} }
private float getDist(MotionTrack control,Vector3f temp, Vector3f tmpVector) { /**
tmpVector.set(temp); * computes the distance between the spatial position and the temp vector.
return tmpVector.subtractLocal(control.getSpatial().getLocalTranslation()).length(); * @param control the control holding the psatial
* @param temp the temp position
* @param store a temp vector3f to store the result
* @return
*/
private float getDist(MotionTrack control, Vector3f temp, Vector3f store) {
store.set(temp);
return store.subtractLocal(control.getSpatial().getLocalTranslation()).length();
} }
private void attachDebugNode(Node root) { private void attachDebugNode(Node root) {
@ -178,6 +208,26 @@ public class MotionPath implements Savable {
} }
/**
* compute the index of the waypoint and the interpolation value according to a distance
* returns a vector 2 containing the index in the x field and the interpolation value in the y field
* @param distance the distance traveled on this path
* @return the waypoint index and the interpolation value in a vector2
*/
public Vector2f getWayPointIndexForDistance(float distance) {
float sum = 0;
distance = distance % spline.getTotalLength();
int i = 0;
for (Float len : spline.getSegmentsLength()) {
if (sum + len >= distance) {
return new Vector2f((float) i, (distance - sum) / len);
}
sum += len;
i++;
}
return new Vector2f((float) spline.getControlPoints().size() - 1, 1.0f);
}
/** /**
* Addsa waypoint to the path * Addsa waypoint to the path
* @param wayPoint a position in world space * @param wayPoint a position in world space
@ -360,4 +410,8 @@ public class MotionPath implements Savable {
public boolean isCycle() { public boolean isCycle() {
return spline.isCycle(); return spline.isCycle();
} }
public Spline getSpline() {
return spline;
}
} }

@ -90,6 +90,10 @@ public class TimeLine extends HashMap<Integer, KeyFrame> implements Savable {
return Math.round(time * keyFramesPerSeconds); return Math.round(time * keyFramesPerSeconds);
} }
public float getKeyFrameTime(KeyFrame keyFrame) {
return (float)keyFrame.getIndex()/(float)keyFramesPerSeconds;
}
public Collection<KeyFrame> getAllKeyFrames() { public Collection<KeyFrame> getAllKeyFrames() {
return values(); return values();
} }

@ -320,4 +320,23 @@ public abstract class AbstractCinematicEvent implements CinematicEvent {
public void removeListener(CinematicEventListener listener) { public void removeListener(CinematicEventListener listener) {
getListeners().remove(listener); getListeners().remove(listener);
} }
/**
* When this method is invoked, the event should fast forward to the given time according tim 0 is the start of the event.
* @param time the time to fast forward to
*/
public void setTime(float time) {
elapsedTimePause = time/speed;
if(playState == PlayState.Playing){
start = timer.getTimeInSeconds();
}
}
public float getTime() {
return time;
}
} }

@ -103,12 +103,33 @@ public class AnimationTrack extends AbstractCinematicEvent {
} }
} }
@Override
public void setTime(float time) {
super.setTime(time);
float t = time;
if(loopMode == loopMode.Loop){
t = t % channel.getAnimMaxTime();
}
if(loopMode == loopMode.Cycle){
float parity = (float)Math.ceil(time / channel.getAnimMaxTime());
if(parity >0 && parity%2 ==0){
t = channel.getAnimMaxTime() - t % channel.getAnimMaxTime();
}else{
t = t % channel.getAnimMaxTime();
}
}
channel.setTime(t);
}
@Override @Override
public void onPlay() { public void onPlay() {
channel.getControl().setEnabled(true); channel.getControl().setEnabled(true);
if (playState == PlayState.Stopped) { if (playState == PlayState.Stopped) {
channel.setAnim(animationName); channel.setAnim(animationName);
channel.setSpeed(speed); channel.setSpeed(speed);
channel.setLoopMode(loopMode);
channel.setTime(time);
} }
} }

@ -60,7 +60,7 @@ public interface CinematicEvent extends Savable {
/** /**
* Returns the actual duration of the animation * Returns the actual duration of the animation
* @return * @return the duration
*/ */
public float getDuration(); public float getDuration();
@ -72,13 +72,13 @@ public interface CinematicEvent extends Savable {
/** /**
* returns the speed of the animation * returns the speed of the animation
* @return * @return the speed
*/ */
public float getSpeed(); public float getSpeed();
/** /**
* returns the PlayState of the animation * returns the PlayState of the animation
* @return * @return the plat state
*/ */
public PlayState getPlayState(); public PlayState getPlayState();
@ -104,7 +104,7 @@ public interface CinematicEvent extends Savable {
/** /**
* returns the initial duration of the animation at speed = 1 in seconds. * returns the initial duration of the animation at speed = 1 in seconds.
* @return * @return the initial duration
*/ */
public float getInitialDuration(); public float getInitialDuration();
@ -114,8 +114,30 @@ public interface CinematicEvent extends Savable {
*/ */
public void setInitialDuration(float initialDuration); public void setInitialDuration(float initialDuration);
/**
* called internally in the update method, place here anything you want to run in the update loop
* @param tpf time per frame
*/
public void internalUpdate(float tpf); public void internalUpdate(float tpf);
/**
* initialize this event
* @param app the application
* @param cinematic the cinematic
*/
public void initEvent(Application app, Cinematic cinematic); public void initEvent(Application app, Cinematic cinematic);
/**
* When this method is invoked, the event should fast forward to the given time according tim 0 is the start of the event.
* @param time the time to fast forward to
*/
public void setTime(float time);
/**
* returns the current time of the cinematic event
* @return the time
*/
public float getTime();
} }

@ -41,11 +41,13 @@ import com.jme3.export.JmeExporter;
import com.jme3.export.JmeImporter; import com.jme3.export.JmeImporter;
import com.jme3.export.OutputCapsule; import com.jme3.export.OutputCapsule;
import com.jme3.math.Quaternion; import com.jme3.math.Quaternion;
import com.jme3.math.Vector2f;
import com.jme3.math.Vector3f; import com.jme3.math.Vector3f;
import com.jme3.renderer.RenderManager; import com.jme3.renderer.RenderManager;
import com.jme3.renderer.ViewPort; import com.jme3.renderer.ViewPort;
import com.jme3.scene.Spatial; import com.jme3.scene.Spatial;
import com.jme3.scene.control.Control; import com.jme3.scene.control.Control;
import com.jme3.util.TempVars;
import java.io.IOException; import java.io.IOException;
/** /**
@ -68,6 +70,11 @@ public class MotionTrack extends AbstractCinematicEvent implements Control {
protected MotionPath path; protected MotionPath path;
private boolean isControl = true; private boolean isControl = true;
/**
* the distance traveled by the spatial on the path
*/
protected float traveledDistance = 0;
/** /**
* Enum for the different type of target direction behavior * Enum for the different type of target direction behavior
@ -167,18 +174,39 @@ public class MotionTrack extends AbstractCinematicEvent implements Control {
} }
} }
} }
} }
@Override @Override
public void initEvent(Application app, Cinematic cinematic) { public void initEvent(Application app, Cinematic cinematic) {
super.initEvent(app, cinematic); super.initEvent(app, cinematic);
isControl = false; isControl = false;
// timer = null;
} }
@Override
public void setTime(float time) {
super.setTime(time);
//computing traveled distance according to new time
traveledDistance = time * (path.getLength() / initialDuration);
TempVars vars = TempVars.get();
Vector3f temp = vars.vect1;
//getting waypoint index and current value from new traveled distance
Vector2f v = path.getWayPointIndexForDistance(traveledDistance);
//setting values
currentWayPoint = (int)v.x;
setCurrentValue(v.y);
//interpolating new position
path.getSpline().interpolate(getCurrentValue(), getCurrentWayPoint(), temp);
//setting new position to the spatial
spatial.setLocalTranslation(temp);
vars.release();
}
public void onUpdate(float tpf) { public void onUpdate(float tpf) {
path.interpolatePath(tpf * speed, this); traveledDistance = path.interpolatePath(time, this);
computeTargetDirection(); computeTargetDirection();
if (currentValue >= 1.0f) { if (currentValue >= 1.0f) {
@ -423,4 +451,14 @@ public class MotionTrack extends AbstractCinematicEvent implements Control {
public Spatial getSpatial() { public Spatial getSpatial() {
return spatial; return spatial;
} }
/**
* return the distance traveled by the spatial on the path
* @return
*/
public float getTraveledDistance() {
return traveledDistance;
}
} }

@ -110,13 +110,17 @@ public class SoundTrack extends AbstractCinematicEvent {
super.initEvent(app, cinematic); super.initEvent(app, cinematic);
audioNode = new AudioNode(app.getAssetManager(), path, stream); audioNode = new AudioNode(app.getAssetManager(), path, stream);
setLoopMode(loopMode); setLoopMode(loopMode);
}
@Override
public void setTime(float time) {
super.setTime(time);
//TODO has to be implemented in the audioRenderer
} }
@Override @Override
public void onPlay() { public void onPlay() {
audioNode.play(); audioNode.play();
} }
@Override @Override

@ -136,6 +136,10 @@ public class FadeFilter extends Filter {
} }
public void pause() {
playing = false;
}
@Override @Override
public void write(JmeExporter ex) throws IOException { public void write(JmeExporter ex) throws IOException {
super.write(ex); super.write(ex);
@ -166,5 +170,8 @@ public class FadeFilter extends Filter {
*/ */
public void setValue(float value) { public void setValue(float value) {
this.value = value; this.value = value;
if (material != null) {
material.setFloat("Value", value);
}
} }
} }

@ -55,32 +55,30 @@ public class GuiTrack extends AbstractCinematicEvent {
public GuiTrack(Nifty nifty, String screen) { public GuiTrack(Nifty nifty, String screen) {
this.screen = screen; this.screen = screen;
this.nifty = nifty;
} }
public GuiTrack(Nifty nifty, String screen, float initialDuration) { public GuiTrack(Nifty nifty, String screen, float initialDuration) {
super(initialDuration); super(initialDuration);
this.screen = screen; this.screen = screen;
this.nifty = nifty;
} }
public GuiTrack(Nifty nifty, String screen, LoopMode loopMode) { public GuiTrack(Nifty nifty, String screen, LoopMode loopMode) {
super(loopMode); super(loopMode);
this.screen = screen; this.screen = screen;
this.nifty = nifty;
} }
public GuiTrack(Nifty nifty, String screen, float initialDuration, LoopMode loopMode) { public GuiTrack(Nifty nifty, String screen, float initialDuration, LoopMode loopMode) {
super(initialDuration, loopMode); super(initialDuration, loopMode);
this.screen = screen; this.screen = screen;
} this.nifty = nifty;
@Override
public void initEvent(Application app, Cinematic cinematic) {
super.initEvent(app, cinematic);
// nifty = cinematic.getNifty();
} }
@Override @Override
public void onPlay() { public void onPlay() {
System.out.println("screen should be "+screen);
nifty.gotoScreen(screen); nifty.gotoScreen(screen);
} }

@ -57,7 +57,6 @@ import com.jme3.scene.Geometry;
import com.jme3.scene.Spatial; import com.jme3.scene.Spatial;
import com.jme3.scene.shape.Box; import com.jme3.scene.shape.Box;
import com.jme3.shadow.PssmShadowRenderer; import com.jme3.shadow.PssmShadowRenderer;
import com.jme3.system.NanoTimer;
import de.lessvoid.nifty.Nifty; import de.lessvoid.nifty.Nifty;
public class TestCinematic extends SimpleApplication { public class TestCinematic extends SimpleApplication {
@ -70,6 +69,7 @@ public class TestCinematic extends SimpleApplication {
private ChaseCamera chaseCam; private ChaseCamera chaseCam;
private FilterPostProcessor fpp; private FilterPostProcessor fpp;
private FadeFilter fade; private FadeFilter fade;
private float time = 0;
public static void main(String[] args) { public static void main(String[] args) {
TestCinematic app = new TestCinematic(); TestCinematic app = new TestCinematic();
@ -101,33 +101,13 @@ public class TestCinematic extends SimpleApplication {
createScene(); createScene();
cinematic = new Cinematic(rootNode, 20); cinematic = new Cinematic(rootNode, 20);
// cinematic.bindUi("Interface/Nifty/CinematicTest.xml");
stateManager.attach(cinematic); stateManager.attach(cinematic);
createCameraMotion(); createCameraMotion();
cinematic.addCinematicEvent(0, new AbstractCinematicEvent() { //fade in
cinematic.addCinematicEvent(0, new FadeEvent(true));
@Override
public void onPlay() {
fade.setDuration(1f / cinematic.getSpeed());
fade.setValue(0);
fade.fadeIn();
}
@Override
public void onUpdate(float tpf) {
}
@Override
public void onStop() {
}
@Override
public void onPause() {
}
});
cinematic.addCinematicEvent(0, new PositionTrack(teapot, new Vector3f(10, 0, 10), 0)); cinematic.addCinematicEvent(0, new PositionTrack(teapot, new Vector3f(10, 0, 10), 0));
cinematic.addCinematicEvent(0, new ScaleTrack(teapot, new Vector3f(1, 1, 1), 0)); cinematic.addCinematicEvent(0, new ScaleTrack(teapot, new Vector3f(1, 1, 1), 0));
Quaternion q = new Quaternion(); Quaternion q = new Quaternion();
@ -143,46 +123,45 @@ public class TestCinematic extends SimpleApplication {
cinematic.activateCamera(0, "aroundCam"); cinematic.activateCamera(0, "aroundCam");
cinematic.addCinematicEvent(0, cameraMotionTrack); cinematic.addCinematicEvent(0, cameraMotionTrack);
cinematic.addCinematicEvent(0, new SoundTrack("Sound/Environment/Nature.ogg", LoopMode.Loop)); cinematic.addCinematicEvent(0, new SoundTrack("Sound/Environment/Nature.ogg", LoopMode.Loop));
cinematic.addCinematicEvent(3, new SoundTrack("Sound/Effects/kick.wav")); cinematic.addCinematicEvent(3f, new SoundTrack("Sound/Effects/kick.wav"));
cinematic.addCinematicEvent(3, new SubtitleTrack(nifty, "start", 3, "jMonkey engine really kicks A...")); cinematic.addCinematicEvent(3, new SubtitleTrack(nifty, "start", 3, "jMonkey engine really kicks A..."));
cinematic.addCinematicEvent(5.0f, new SoundTrack("Sound/Effects/Beep.ogg", 1)); cinematic.addCinematicEvent(5.1f, new SoundTrack("Sound/Effects/Beep.ogg", 1));
cinematic.addCinematicEvent(6, new AnimationTrack(model, "Walk", LoopMode.Loop)); cinematic.addCinematicEvent(2, new AnimationTrack(model, "Walk", LoopMode.Loop));
cinematic.activateCamera(6, "topView"); cinematic.activateCamera(6, "topView");
cinematic.activateCamera(10, "aroundCam"); cinematic.activateCamera(10, "aroundCam");
cinematic.addCinematicEvent(19, new AbstractCinematicEvent() { //fade out
cinematic.addCinematicEvent(19, new FadeEvent(false));
@Override // cinematic.addCinematicEvent(19, new AbstractCinematicEvent() {
public void onPlay() { //
fade.setDuration(1f / cinematic.getSpeed()); // @Override
fade.fadeOut(); // public void onPlay() {
} // fade.setDuration(1f / cinematic.getSpeed());
// fade.fadeOut();
@Override //
public void onUpdate(float tpf) { // }
} //
// @Override
@Override // public void onUpdate(float tpf) {
public void onStop() { // }
} //
// @Override
@Override // public void onStop() {
public void onPause() { // }
} //
}); // @Override
// public void onPause() {
// }
// });
final NanoTimer myTimer = new NanoTimer();
cinematic.addListener(new CinematicEventListener() { cinematic.addListener(new CinematicEventListener() {
public void onPlay(CinematicEvent cinematic) { public void onPlay(CinematicEvent cinematic) {
chaseCam.setEnabled(false); chaseCam.setEnabled(false);
myTimer.reset();
System.out.println("play"); System.out.println("play");
} }
public void onPause(CinematicEvent cinematic) { public void onPause(CinematicEvent cinematic) {
chaseCam.setEnabled(true);
System.out.println("pause"); System.out.println("pause");
} }
@ -190,12 +169,10 @@ public class TestCinematic extends SimpleApplication {
chaseCam.setEnabled(true); chaseCam.setEnabled(true);
fade.setValue(1); fade.setValue(1);
System.out.println("stop"); System.out.println("stop");
System.out.println((float) myTimer.getTime() / (float) myTimer.getResolution());
} }
}); });
cinematic.setSpeed(2); //cinematic.setSpeed(2);
flyCam.setEnabled(false); flyCam.setEnabled(false);
chaseCam = new ChaseCamera(cam, model, inputManager); chaseCam = new ChaseCamera(cam, model, inputManager);
initInputs(); initInputs();
@ -269,19 +246,90 @@ public class TestCinematic extends SimpleApplication {
private void initInputs() { private void initInputs() {
inputManager.addMapping("togglePause", new KeyTrigger(keyInput.KEY_RETURN)); inputManager.addMapping("togglePause", new KeyTrigger(keyInput.KEY_RETURN));
inputManager.addMapping("navFwd", new KeyTrigger(keyInput.KEY_RIGHT));
inputManager.addMapping("navBack", new KeyTrigger(keyInput.KEY_LEFT));
ActionListener acl = new ActionListener() { ActionListener acl = new ActionListener() {
public void onAction(String name, boolean keyPressed, float tpf) { public void onAction(String name, boolean keyPressed, float tpf) {
if (name.equals("togglePause") && keyPressed) { if (name.equals("togglePause") && keyPressed) {
if (cinematic.getPlayState() == PlayState.Playing) { if (cinematic.getPlayState() == PlayState.Playing) {
cinematic.pause(); cinematic.pause();
time = cinematic.getTime();
} else { } else {
cinematic.play(); cinematic.play();
} }
} }
if (cinematic.getPlayState() != PlayState.Playing) {
if (name.equals("navFwd") && keyPressed) {
time += 0.25;
FastMath.clamp(time, 0, cinematic.getInitialDuration());
cinematic.setTime(time);
}
if (name.equals("navBack") && keyPressed) {
time -= 0.25;
FastMath.clamp(time, 0, cinematic.getInitialDuration());
cinematic.setTime(time);
}
}
} }
}; };
inputManager.addListener(acl, "togglePause"); inputManager.addListener(acl, "togglePause", "navFwd", "navBack");
}
private class FadeEvent extends AbstractCinematicEvent {
boolean in = true;
float value = 0;
public FadeEvent(boolean in) {
super(1);
this.in = in;
value = in ? 0 : 1;
}
@Override
public void onPlay() {
fade.setDuration(1f / cinematic.getSpeed());
if (in) {
fade.fadeIn();
} else {
fade.fadeOut();
}
fade.setValue(value);
}
@Override
public void setTime(float time) {
super.setTime(time);
if (time >= fade.getDuration()) {
value = in ? 1 : 0;
fade.setValue(value);
} else {
value = time;
if (in) {
fade.setValue(time / cinematic.getSpeed());
} else {
fade.setValue(1 - time / cinematic.getSpeed());
}
}
}
@Override
public void onUpdate(float tpf) {
}
@Override
public void onStop() {
}
@Override
public void onPause() {
value = fade.getValue();
fade.pause();
}
} }
} }

@ -83,7 +83,7 @@ public class TestMotionPath extends SimpleApplication {
motionControl.setDirectionType(MotionTrack.Direction.PathAndRotation); motionControl.setDirectionType(MotionTrack.Direction.PathAndRotation);
motionControl.setRotation(new Quaternion().fromAngleNormalAxis(-FastMath.HALF_PI, Vector3f.UNIT_Y)); motionControl.setRotation(new Quaternion().fromAngleNormalAxis(-FastMath.HALF_PI, Vector3f.UNIT_Y));
motionControl.setInitialDuration(10f); motionControl.setInitialDuration(10f);
motionControl.setSpeed(0.1f); motionControl.setSpeed(2f);
guiFont = assetManager.loadFont("Interface/Fonts/Default.fnt"); guiFont = assetManager.loadFont("Interface/Fonts/Default.fnt");
final BitmapText wayPointsText = new BitmapText(guiFont, false); final BitmapText wayPointsText = new BitmapText(guiFont, false);

@ -1,8 +1,8 @@
<?xml version="1.0" encoding="UTF-8"?> <?xml version="1.0" encoding="UTF-8"?>
<nifty xmlns="http://nifty-gui.sourceforge.net/nifty.xsd" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://nifty-gui.sourceforge.net/nifty.xsd http://nifty-gui.sourceforge.net/nifty.xsd"> <nifty>
<screen id="start" controller="de.lessvoid.nifty.examples.helloworld.HelloWorldStartScreen"> <screen id="start" controller="jme3test.niftygui.TestNiftyGui">
<layer id="layer" backgroundColor="#0000" childLayout="center"> <layer id="layer" backgroundColor="#0000" childLayout="center">
<panel id="panel" width="100%" backgroundColor="#0000" childLayout="center" visibleToMouse="true" > <panel id="panel" width="100%" height="100%" backgroundColor="#0000" childLayout="center" visibleToMouse="true" >
<text id="text" font="aurulent-sans-16.fnt" color="#000f" text="" align="center" valign="bottom" /> <text id="text" font="aurulent-sans-16.fnt" color="#000f" text="" align="center" valign="bottom" />
</panel> </panel>
</layer> </layer>

Loading…
Cancel
Save