Browse Source

- fixed bad time calculation on cinematics
- Used a nano timer for precision
- javadoc'ed a bit

git-svn-id: https://jmonkeyengine.googlecode.com/svn/trunk@8443 75d07b2b-3a1a-0410-a2c5-0572b91ccdca

rem..om 14 years ago
parent
commit
be6259e5ba

+ 4 - 5
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() {

+ 93 - 14
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<CinematicEventListener> 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<CinematicEventListener> getListeners() {
         if (listeners == null) {
             listeners = new ArrayList<CinematicEventListener>();
@@ -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);
     }

+ 3 - 0
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

+ 2 - 1
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

+ 10 - 10
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;
 

+ 2 - 2
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);
         }

+ 2 - 2
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);

+ 2 - 2
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));
         }
     }

+ 2 - 1
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);
 

+ 1 - 2
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);
     }
 
 

+ 18 - 0
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");
     }
+
+    
+    
+    
+    
 }