diff --git a/engine/src/core/com/jme3/cinematic/Cinematic.java b/engine/src/core/com/jme3/cinematic/Cinematic.java index 6d8e1f458..63204fe85 100644 --- a/engine/src/core/com/jme3/cinematic/Cinematic.java +++ b/engine/src/core/com/jme3/cinematic/Cinematic.java @@ -166,7 +166,6 @@ public class Cinematic extends AbstractCinematicEvent implements AppState { @Override public void setSpeed(float speed) { super.setSpeed(speed); - duration = initialDuration / speed; for (int i = 0; i < cinematicEvents.size(); i++) { CinematicEvent ce = cinematicEvents.get(i); ce.setSpeed(speed); @@ -185,6 +184,7 @@ public class Cinematic extends AbstractCinematicEvent implements AppState { nifty.fromXmlWithoutStartScreen(niftyXmlPath); app.getGuiViewPort().addProcessor(niftyDisplay); } + initEvent(app, this); for (CinematicEvent cinematicEvent : cinematicEvents) { cinematicEvent.initEvent(app, this); } @@ -203,12 +203,11 @@ public class Cinematic extends AbstractCinematicEvent implements AppState { play(); } } - + public boolean isEnabled() { return playState == PlayState.Playing; } - public void stateAttached(AppStateManager stateManager) { } @@ -303,8 +302,8 @@ public class Cinematic extends AbstractCinematicEvent implements AppState { enableCurrentCam(true); } - public void activateCamera(float time, final String cameraName) { - addCinematicEvent(time, new AbstractCinematicEvent() { + public void activateCamera(float timeStamp, final String cameraName) { + addCinematicEvent(timeStamp, new AbstractCinematicEvent() { @Override public void onPlay() { diff --git a/engine/src/core/com/jme3/cinematic/events/AbstractCinematicEvent.java b/engine/src/core/com/jme3/cinematic/events/AbstractCinematicEvent.java index f6cf49e5c..30722c89e 100644 --- a/engine/src/core/com/jme3/cinematic/events/AbstractCinematicEvent.java +++ b/engine/src/core/com/jme3/cinematic/events/AbstractCinematicEvent.java @@ -39,13 +39,16 @@ import com.jme3.export.InputCapsule; import com.jme3.export.JmeExporter; import com.jme3.export.JmeImporter; import com.jme3.export.OutputCapsule; -import com.jme3.export.Savable; +import com.jme3.system.NanoTimer; import java.io.IOException; import java.util.ArrayList; import java.util.List; /** - * + * This calls contains basic behavior of a cinematic event + * every cinematic event must extend this class + * + * A cinematic event must be given an inital duration in seconds (duration of the event at speed = 1) (default is 10) * @author Nehon */ public abstract class AbstractCinematicEvent implements CinematicEvent { @@ -53,32 +56,61 @@ public abstract class AbstractCinematicEvent implements CinematicEvent { protected PlayState playState = PlayState.Stopped; protected float speed = 1; protected float initialDuration = 10; - protected float duration = initialDuration / speed; protected LoopMode loopMode = LoopMode.DontLoop; protected float time = 0; + //nano timer for precisely computing the elapsed time + protected NanoTimer timer; + /** + * the last time the event was paused + */ + protected float elapsedTimePause = 0; + /** + * the list of listeners + */ protected List listeners; + /** + * contruct a cinematic event + */ public AbstractCinematicEvent() { } + /** + * contruct a cinematic event wwith the given initial duration + * @param initialDuration + */ public AbstractCinematicEvent(float initialDuration) { this.initialDuration = initialDuration; - duration = initialDuration / speed; } + /** + * contruct a cinematic event with the given loopMode + * @param loopMode + */ public AbstractCinematicEvent(LoopMode loopMode) { this.loopMode = loopMode; } + /** + * contruct a cinematic event with the given loopMode and the given initialDuration + * @param initialDuration the duration of the event at speed = 1 + * @param loopMode the loop mode of the event + */ public AbstractCinematicEvent(float initialDuration, LoopMode loopMode) { this.initialDuration = initialDuration; this.loopMode = loopMode; - duration = initialDuration / speed; } + /** + * Play this event + */ public void play() { onPlay(); playState = PlayState.Playing; + if (timer == null) { + timer = new NanoTimer(); + } + timer.reset(); if (listeners != null) { for (int i = 0; i < listeners.size(); i++) { CinematicEventListener cel = listeners.get(i); @@ -87,21 +119,32 @@ public abstract class AbstractCinematicEvent implements CinematicEvent { } } - public abstract void onPlay(); + /** + * Place here the code you want to execute when the event is started + */ + protected abstract void onPlay(); + /** + * should be used internally only + * @param tpf time per frame + */ public void internalUpdate(float tpf) { if (playState == PlayState.Playing) { - time += tpf * speed; + time = (elapsedTimePause + timer.getTimeInSeconds()) * speed; onUpdate(tpf); - if (time >= duration && loopMode == loopMode.DontLoop) { + if (time >= initialDuration && loopMode == loopMode.DontLoop) { stop(); } } } - public abstract void onUpdate(float tpf); + /** + * Place here the code you want to execute on update (only called when the event is playing) + * @param tpf time per frame + */ + protected abstract void onUpdate(float tpf); /** * stops the animation, next time play() is called the animation will start from the begining. @@ -110,6 +153,7 @@ public abstract class AbstractCinematicEvent implements CinematicEvent { onStop(); time = 0; playState = PlayState.Stopped; + elapsedTimePause = 0; if (listeners != null) { for (int i = 0; i < listeners.size(); i++) { CinematicEventListener cel = listeners.get(i); @@ -118,11 +162,18 @@ public abstract class AbstractCinematicEvent implements CinematicEvent { } } - public abstract void onStop(); + /** + * Place here the code you want to execute when the event is stoped. + */ + protected abstract void onStop(); + /** + * pause this event + */ public void pause() { onPause(); playState = PlayState.Paused; + elapsedTimePause = time; if (listeners != null) { for (int i = 0; i < listeners.size(); i++) { CinematicEventListener cel = listeners.get(i); @@ -131,6 +182,9 @@ public abstract class AbstractCinematicEvent implements CinematicEvent { } } + /** + * place here the code you want to execute when the event is paused + */ public abstract void onPause(); /** @@ -138,7 +192,7 @@ public abstract class AbstractCinematicEvent implements CinematicEvent { * @return */ public float getDuration() { - return duration; + return initialDuration / speed; } /** @@ -149,7 +203,6 @@ public abstract class AbstractCinematicEvent implements CinematicEvent { */ public void setSpeed(float speed) { this.speed = speed; - duration = initialDuration / speed; } /** @@ -182,7 +235,6 @@ public abstract class AbstractCinematicEvent implements CinematicEvent { */ public void setInitialDuration(float initialDuration) { this.initialDuration = initialDuration; - duration = initialDuration / speed; } /** @@ -203,6 +255,11 @@ public abstract class AbstractCinematicEvent implements CinematicEvent { this.loopMode = loopMode; } + /** + * for serialization only + * @param ex exporter + * @throws IOException + */ public void write(JmeExporter ex) throws IOException { OutputCapsule oc = ex.getCapsule(this); oc.write(playState, "playState", PlayState.Stopped); @@ -211,18 +268,32 @@ public abstract class AbstractCinematicEvent implements CinematicEvent { oc.write(loopMode, "loopMode", LoopMode.DontLoop); } + /** + * for serialization only + * @param im importer + * @throws IOException + */ public void read(JmeImporter im) throws IOException { InputCapsule ic = im.getCapsule(this); playState = ic.readEnum("playState", PlayState.class, PlayState.Stopped); speed = ic.readFloat("speed", 1); initialDuration = ic.readFloat("initalDuration", 10); - duration = initialDuration / speed; loopMode = ic.readEnum("loopMode", LoopMode.class, LoopMode.DontLoop); } + /** + * initialize this event (should be called internally only) + * @param app + * @param cinematic + */ public void initEvent(Application app, Cinematic cinematic) { + timer = new NanoTimer(); } + /** + * return a list of CinematicEventListener added on this event + * @return + */ private List getListeners() { if (listeners == null) { listeners = new ArrayList(); @@ -230,10 +301,18 @@ public abstract class AbstractCinematicEvent implements CinematicEvent { return listeners; } + /** + * Add a CinematicEventListener to this event + * @param listener CinematicEventListener + */ public void addListener(CinematicEventListener listener) { getListeners().add(listener); } + /** + * remove a CinematicEventListener from this event + * @param listener CinematicEventListener + */ public void removeListener(CinematicEventListener listener) { getListeners().remove(listener); } diff --git a/engine/src/core/com/jme3/cinematic/events/AnimationTrack.java b/engine/src/core/com/jme3/cinematic/events/AnimationTrack.java index 3ba3f6d9a..3e4889e09 100644 --- a/engine/src/core/com/jme3/cinematic/events/AnimationTrack.java +++ b/engine/src/core/com/jme3/cinematic/events/AnimationTrack.java @@ -85,6 +85,7 @@ public class AnimationTrack extends AbstractCinematicEvent { @Override public void initEvent(Application app, Cinematic cinematic) { + super.initEvent(app, cinematic); if (channel == null) { Object s = cinematic.getEventData("modelChannels", modelName); if (s != null && s instanceof AnimChannel) { @@ -107,6 +108,7 @@ public class AnimationTrack extends AbstractCinematicEvent { channel.getControl().setEnabled(true); if (playState == PlayState.Stopped) { channel.setAnim(animationName); + channel.setSpeed(speed); } } @@ -117,6 +119,7 @@ public class AnimationTrack extends AbstractCinematicEvent { @Override public void onStop() { channel.getControl().setEnabled(false); + channel.setTime(0); } @Override diff --git a/engine/src/core/com/jme3/cinematic/events/GuiTrack.java b/engine/src/core/com/jme3/cinematic/events/GuiTrack.java index d9b0daff5..f3b1f2565 100644 --- a/engine/src/core/com/jme3/cinematic/events/GuiTrack.java +++ b/engine/src/core/com/jme3/cinematic/events/GuiTrack.java @@ -75,12 +75,13 @@ public class GuiTrack extends AbstractCinematicEvent { @Override public void initEvent(Application app, Cinematic cinematic) { + super.initEvent(app, cinematic); nifty = cinematic.getNifty(); } @Override public void onPlay() { - nifty.gotoScreen(screen); + nifty.gotoScreen(screen); } @Override diff --git a/engine/src/core/com/jme3/cinematic/events/MotionTrack.java b/engine/src/core/com/jme3/cinematic/events/MotionTrack.java index bc196be44..3221926c3 100644 --- a/engine/src/core/com/jme3/cinematic/events/MotionTrack.java +++ b/engine/src/core/com/jme3/cinematic/events/MotionTrack.java @@ -46,6 +46,7 @@ import com.jme3.renderer.RenderManager; import com.jme3.renderer.ViewPort; import com.jme3.scene.Spatial; import com.jme3.scene.control.Control; +import com.jme3.system.NanoTimer; import java.io.IOException; /** @@ -66,7 +67,7 @@ public class MotionTrack extends AbstractCinematicEvent implements Control { protected Quaternion rotation; protected Direction directionType = Direction.None; protected MotionPath path; - private boolean isControl=true; + private boolean isControl = true; /** @@ -157,11 +158,12 @@ public class MotionTrack extends AbstractCinematicEvent implements Control { } public void update(float tpf) { - if(isControl){ + if (isControl) { + if (playState == PlayState.Playing) { - time += tpf * speed; + time = (elapsedTimePause + timer.getTimeInSeconds()) * speed; onUpdate(tpf); - if (time >= duration && loopMode == loopMode.DontLoop) { + if (time >= initialDuration && loopMode == loopMode.DontLoop) { stop(); } } @@ -171,13 +173,13 @@ public class MotionTrack extends AbstractCinematicEvent implements Control { @Override public void initEvent(Application app, Cinematic cinematic) { - isControl=false; + super.initEvent(app, cinematic); + isControl = false; + timer = null; } - - public void onUpdate(float tpf) { - spatial.setLocalTranslation(path.interpolatePath(tpf, this)); + spatial.setLocalTranslation(path.interpolatePath(tpf * speed, this)); computeTargetDirection(); if (currentValue >= 1.0f) { @@ -270,10 +272,8 @@ public class MotionTrack extends AbstractCinematicEvent implements Control { control.lookAt = lookAt.clone(); control.upVector = upVector.clone(); control.rotation = rotation.clone(); - control.duration = duration; control.initialDuration = initialDuration; control.speed = speed; - control.duration = duration; control.loopMode = loopMode; control.directionType = directionType; diff --git a/engine/src/core/com/jme3/cinematic/events/PositionTrack.java b/engine/src/core/com/jme3/cinematic/events/PositionTrack.java index d085038ea..c4aa18dc6 100644 --- a/engine/src/core/com/jme3/cinematic/events/PositionTrack.java +++ b/engine/src/core/com/jme3/cinematic/events/PositionTrack.java @@ -78,7 +78,7 @@ public class PositionTrack extends AbstractCinematicEvent { if (playState != playState.Paused) { startPosition = spatial.getWorldTranslation().clone(); } - if (duration == 0 && spatial != null) { + if (initialDuration == 0 && spatial != null) { spatial.setLocalTranslation(endPosition); } @@ -87,7 +87,7 @@ public class PositionTrack extends AbstractCinematicEvent { @Override public void onUpdate(float tpf) { if (spatial != null) { - value += Math.min(tpf * speed / duration, 1.0f); + value = Math.min(time / initialDuration, 1.0f); Vector3f pos = FastMath.interpolateLinear(value, startPosition, endPosition); spatial.setLocalTranslation(pos); } diff --git a/engine/src/core/com/jme3/cinematic/events/RotationTrack.java b/engine/src/core/com/jme3/cinematic/events/RotationTrack.java index 99606729b..08e1850b3 100644 --- a/engine/src/core/com/jme3/cinematic/events/RotationTrack.java +++ b/engine/src/core/com/jme3/cinematic/events/RotationTrack.java @@ -78,7 +78,7 @@ public class RotationTrack extends AbstractCinematicEvent { if (playState != playState.Paused) { startRotation.set(spatial.getWorldRotation()); } - if (duration == 0 && spatial != null) { + if (initialDuration == 0 && spatial != null) { spatial.setLocalRotation(endRotation); stop(); } @@ -87,7 +87,7 @@ public class RotationTrack extends AbstractCinematicEvent { @Override public void onUpdate(float tpf) { if (spatial != null) { - value += Math.min(tpf * speed / duration, 1.0f); + value = Math.min(time / initialDuration, 1.0f); TempVars vars = TempVars.get(); Quaternion q = vars.quat1; q.set(startRotation).slerp(endRotation, value); diff --git a/engine/src/core/com/jme3/cinematic/events/ScaleTrack.java b/engine/src/core/com/jme3/cinematic/events/ScaleTrack.java index 923f87f88..60fd7d662 100644 --- a/engine/src/core/com/jme3/cinematic/events/ScaleTrack.java +++ b/engine/src/core/com/jme3/cinematic/events/ScaleTrack.java @@ -78,7 +78,7 @@ public class ScaleTrack extends AbstractCinematicEvent { if (playState != playState.Paused) { startScale = spatial.getWorldScale().clone(); } - if (duration == 0 && spatial != null) { + if (initialDuration == 0 && spatial != null) { spatial.setLocalScale(endScale); stop(); } @@ -87,7 +87,7 @@ public class ScaleTrack extends AbstractCinematicEvent { @Override public void onUpdate(float tpf) { if (spatial != null) { - value += Math.min(tpf * speed / duration, 1.0f); + value = Math.min(time / initialDuration, 1.0f); spatial.setLocalScale(FastMath.interpolateLinear(value, startScale, endScale)); } } diff --git a/engine/src/core/com/jme3/cinematic/events/SoundTrack.java b/engine/src/core/com/jme3/cinematic/events/SoundTrack.java index 9caeffa39..c0b5ace59 100644 --- a/engine/src/core/com/jme3/cinematic/events/SoundTrack.java +++ b/engine/src/core/com/jme3/cinematic/events/SoundTrack.java @@ -107,7 +107,8 @@ public class SoundTrack extends AbstractCinematicEvent { } @Override - public void initEvent(Application app, Cinematic cinematic) { + public void initEvent(Application app, Cinematic cinematic) { + super.initEvent(app, cinematic); audioNode = new AudioNode(app.getAssetManager(), path, stream); setLoopMode(loopMode); diff --git a/engine/src/test/jme3test/animation/SubtitleTrack.java b/engine/src/test/jme3test/animation/SubtitleTrack.java index d4def9493..1cb56725a 100644 --- a/engine/src/test/jme3test/animation/SubtitleTrack.java +++ b/engine/src/test/jme3test/animation/SubtitleTrack.java @@ -23,8 +23,7 @@ public class SubtitleTrack extends GuiTrack{ @Override public void onPlay() { super.onPlay(); - //REMY FIX THIS - //nifty.getScreen(screen).findElementByName("text").getRenderer(TextRenderer.class).changeText(text); + nifty.getScreen(screen).findElementByName("text").getRenderer(TextRenderer.class).setText(text); } diff --git a/engine/src/test/jme3test/animation/TestCinematic.java b/engine/src/test/jme3test/animation/TestCinematic.java index 3b14d6e0e..c4852de0b 100644 --- a/engine/src/test/jme3test/animation/TestCinematic.java +++ b/engine/src/test/jme3test/animation/TestCinematic.java @@ -64,6 +64,8 @@ import com.jme3.scene.Geometry; import com.jme3.scene.Spatial; import com.jme3.scene.shape.Box; import com.jme3.shadow.PssmShadowRenderer; +import com.jme3.system.NanoTimer; +import com.jme3.system.lwjgl.LwjglTimer; public class TestCinematic extends SimpleApplication { @@ -79,6 +81,8 @@ public class TestCinematic extends SimpleApplication { public static void main(String[] args) { TestCinematic app = new TestCinematic(); app.start(); + + } @@ -106,6 +110,7 @@ public class TestCinematic extends SimpleApplication { @Override public void onPlay() { + fade.setDuration(1f/cinematic.getSpeed()); fade.setValue(0); fade.fadeIn(); } @@ -148,6 +153,7 @@ public class TestCinematic extends SimpleApplication { @Override public void onPlay() { + fade.setDuration(1f/cinematic.getSpeed()); fade.fadeOut(); } @@ -164,10 +170,13 @@ public class TestCinematic extends SimpleApplication { } }); + final NanoTimer myTimer = new NanoTimer(); cinematic.addListener(new CinematicEventListener() { public void onPlay(CinematicEvent cinematic) { chaseCam.setEnabled(false); + myTimer.reset(); + System.out.println("play"); } @@ -180,9 +189,13 @@ public class TestCinematic extends SimpleApplication { chaseCam.setEnabled(true); fade.setValue(1); System.out.println("stop"); + System.out.println((float)myTimer.getTime()/(float)myTimer.getResolution()); + } + }); + cinematic.setSpeed(2); flyCam.setEnabled(false); chaseCam = new ChaseCamera(cam, model, inputManager); initInputs(); @@ -270,4 +283,9 @@ public class TestCinematic extends SimpleApplication { }; inputManager.addListener(acl, "togglePause"); } + + + + + }