Trying to make Cinematic serialization work.

This way at least it doesn't crash: Removed anonymous inner class and made new class; CameraEvent
Added a bunch of default constructors for other related classes in the process.
empirephoenix-patch-1
Rickard Edén 7 years ago committed by Rémy Bouquet
parent 2120c9d334
commit ae97614c83
  1. 734
      jme3-core/src/main/java/com/jme3/animation/AnimChannel.java
  2. 4
      jme3-core/src/main/java/com/jme3/animation/AnimationUtils.java
  3. 1426
      jme3-core/src/main/java/com/jme3/cinematic/Cinematic.java
  4. 182
      jme3-core/src/main/java/com/jme3/cinematic/KeyFrame.java
  5. 895
      jme3-core/src/main/java/com/jme3/cinematic/events/AnimationEvent.java
  6. 146
      jme3-core/src/main/java/com/jme3/cinematic/events/CameraEvent.java
  7. 982
      jme3-core/src/main/java/com/jme3/cinematic/events/MotionEvent.java
  8. 459
      jme3-core/src/main/java/com/jme3/cinematic/events/SoundEvent.java
  9. 245
      jme3-core/src/main/java/com/jme3/scene/CameraNode.java

@ -1,365 +1,369 @@
/* /*
* Copyright (c) 2009-2012 jMonkeyEngine * Copyright (c) 2009-2012 jMonkeyEngine
* All rights reserved. * All rights reserved.
* *
* Redistribution and use in source and binary forms, with or without * Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are * modification, are permitted provided that the following conditions are
* met: * met:
* *
* * Redistributions of source code must retain the above copyright * * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer. * notice, this list of conditions and the following disclaimer.
* *
* * Redistributions in binary form must reproduce the above copyright * * Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the * notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution. * documentation and/or other materials provided with the distribution.
* *
* * Neither the name of 'jMonkeyEngine' nor the names of its contributors * * Neither the name of 'jMonkeyEngine' nor the names of its contributors
* may be used to endorse or promote products derived from this software * may be used to endorse or promote products derived from this software
* without specific prior written permission. * without specific prior written permission.
* *
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
* TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
* PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/ */
package com.jme3.animation; package com.jme3.animation;
import com.jme3.math.FastMath; import com.jme3.math.FastMath;
import com.jme3.util.TempVars; import com.jme3.util.TempVars;
import java.util.BitSet; import java.util.BitSet;
/** /**
* <code>AnimChannel</code> provides controls, such as play, pause, * <code>AnimChannel</code> provides controls, such as play, pause,
* fast forward, etc, for an animation. The animation * fast forward, etc, for an animation. The animation
* channel may influence the entire model or specific bones of the model's * channel may influence the entire model or specific bones of the model's
* skeleton. A single model may have multiple animation channels influencing * skeleton. A single model may have multiple animation channels influencing
* various parts of its body. For example, a character model may have an * various parts of its body. For example, a character model may have an
* animation channel for its feet, and another for its torso, and * animation channel for its feet, and another for its torso, and
* the animations for each channel are controlled independently. * the animations for each channel are controlled independently.
* *
* @author Kirill Vainer * @author Kirill Vainer
*/ */
public final class AnimChannel { public final class AnimChannel {
private static final float DEFAULT_BLEND_TIME = 0.15f; private static final float DEFAULT_BLEND_TIME = 0.15f;
private AnimControl control; private AnimControl control;
private BitSet affectedBones; private BitSet affectedBones;
private Animation animation; private Animation animation;
private Animation blendFrom; private Animation blendFrom;
private float time; private float time;
private float speed; private float speed;
private float timeBlendFrom; private float timeBlendFrom;
private float blendTime; private float blendTime;
private float speedBlendFrom; private float speedBlendFrom;
private boolean notified=false; private boolean notified=false;
private LoopMode loopMode, loopModeBlendFrom; private LoopMode loopMode, loopModeBlendFrom;
private float blendAmount = 1f; private float blendAmount = 1f;
private float blendRate = 0; private float blendRate = 0;
AnimChannel(AnimControl control){ public AnimChannel(){
this.control = control;
} }
/** public AnimChannel(AnimControl control){
* Returns the parent control of this AnimChannel. this.control = control;
* }
* @return the parent control of this AnimChannel.
* @see AnimControl /**
*/ * Returns the parent control of this AnimChannel.
public AnimControl getControl() { *
return control; * @return the parent control of this AnimChannel.
} * @see AnimControl
*/
/** public AnimControl getControl() {
* @return The name of the currently playing animation, or null if return control;
* none is assigned. }
*
* @see AnimChannel#setAnim(java.lang.String) /**
*/ * @return The name of the currently playing animation, or null if
public String getAnimationName() { * none is assigned.
return animation != null ? animation.getName() : null; *
} * @see AnimChannel#setAnim(java.lang.String)
*/
/** public String getAnimationName() {
* @return The loop mode currently set for the animation. The loop mode return animation != null ? animation.getName() : null;
* determines what will happen to the animation once it finishes }
* playing.
* /**
* For more information, see the LoopMode enum class. * @return The loop mode currently set for the animation. The loop mode
* @see LoopMode * determines what will happen to the animation once it finishes
* @see AnimChannel#setLoopMode(com.jme3.animation.LoopMode) * playing.
*/ *
public LoopMode getLoopMode() { * For more information, see the LoopMode enum class.
return loopMode; * @see LoopMode
} * @see AnimChannel#setLoopMode(com.jme3.animation.LoopMode)
*/
/** public LoopMode getLoopMode() {
* @param loopMode Set the loop mode for the channel. The loop mode return loopMode;
* determines what will happen to the animation once it finishes }
* playing.
* /**
* For more information, see the LoopMode enum class. * @param loopMode Set the loop mode for the channel. The loop mode
* @see LoopMode * determines what will happen to the animation once it finishes
*/ * playing.
public void setLoopMode(LoopMode loopMode) { *
this.loopMode = loopMode; * For more information, see the LoopMode enum class.
} * @see LoopMode
*/
/** public void setLoopMode(LoopMode loopMode) {
* @return The speed that is assigned to the animation channel. The speed this.loopMode = loopMode;
* is a scale value starting from 0.0, at 1.0 the animation will play }
* at its default speed.
* /**
* @see AnimChannel#setSpeed(float) * @return The speed that is assigned to the animation channel. The speed
*/ * is a scale value starting from 0.0, at 1.0 the animation will play
public float getSpeed() { * at its default speed.
return speed; *
} * @see AnimChannel#setSpeed(float)
*/
/** public float getSpeed() {
* @param speed Set the speed of the animation channel. The speed return speed;
* is a scale value starting from 0.0, at 1.0 the animation will play }
* at its default speed.
*/ /**
public void setSpeed(float speed) { * @param speed Set the speed of the animation channel. The speed
this.speed = speed; * is a scale value starting from 0.0, at 1.0 the animation will play
if(blendTime>0){ * at its default speed.
this.speedBlendFrom = speed; */
blendTime = Math.min(blendTime, animation.getLength() / speed); public void setSpeed(float speed) {
blendRate = 1/ blendTime; this.speed = speed;
} if(blendTime>0){
} this.speedBlendFrom = speed;
blendTime = Math.min(blendTime, animation.getLength() / speed);
/** blendRate = 1/ blendTime;
* @return The time of the currently playing animation. The time }
* starts at 0 and continues on until getAnimMaxTime(). }
*
* @see AnimChannel#setTime(float) /**
*/ * @return The time of the currently playing animation. The time
public float getTime() { * starts at 0 and continues on until getAnimMaxTime().
return time; *
} * @see AnimChannel#setTime(float)
*/
/** public float getTime() {
* @param time Set the time of the currently playing animation, the time return time;
* is clamped from 0 to {@link #getAnimMaxTime()}. }
*/
public void setTime(float time) { /**
this.time = FastMath.clamp(time, 0, getAnimMaxTime()); * @param time Set the time of the currently playing animation, the time
} * is clamped from 0 to {@link #getAnimMaxTime()}.
*/
/** public void setTime(float time) {
* @return The length of the currently playing animation, or zero this.time = FastMath.clamp(time, 0, getAnimMaxTime());
* if no animation is playing. }
*
* @see AnimChannel#getTime() /**
*/ * @return The length of the currently playing animation, or zero
public float getAnimMaxTime(){ * if no animation is playing.
return animation != null ? animation.getLength() : 0f; *
} * @see AnimChannel#getTime()
*/
/** public float getAnimMaxTime(){
* Set the current animation that is played by this AnimChannel. return animation != null ? animation.getLength() : 0f;
* <p> }
* This resets the time to zero, and optionally blends the animation
* over <code>blendTime</code> seconds with the currently playing animation. /**
* Notice that this method will reset the control's speed to 1.0. * Set the current animation that is played by this AnimChannel.
* * <p>
* @param name The name of the animation to play * This resets the time to zero, and optionally blends the animation
* @param blendTime The blend time over which to blend the new animation * over <code>blendTime</code> seconds with the currently playing animation.
* with the old one. If zero, then no blending will occur and the new * Notice that this method will reset the control's speed to 1.0.
* animation will be applied instantly. *
*/ * @param name The name of the animation to play
public void setAnim(String name, float blendTime){ * @param blendTime The blend time over which to blend the new animation
if (name == null) * with the old one. If zero, then no blending will occur and the new
throw new IllegalArgumentException("name cannot be null"); * animation will be applied instantly.
*/
if (blendTime < 0f) public void setAnim(String name, float blendTime){
throw new IllegalArgumentException("blendTime cannot be less than zero"); if (name == null)
throw new IllegalArgumentException("name cannot be null");
Animation anim = control.animationMap.get(name);
if (anim == null) if (blendTime < 0f)
throw new IllegalArgumentException("Cannot find animation named: '"+name+"'"); throw new IllegalArgumentException("blendTime cannot be less than zero");
control.notifyAnimChange(this, name); Animation anim = control.animationMap.get(name);
if (anim == null)
if (animation != null && blendTime > 0f){ throw new IllegalArgumentException("Cannot find animation named: '"+name+"'");
this.blendTime = blendTime;
// activate blending control.notifyAnimChange(this, name);
blendTime = Math.min(blendTime, anim.getLength() / speed);
blendFrom = animation; if (animation != null && blendTime > 0f){
timeBlendFrom = time; this.blendTime = blendTime;
speedBlendFrom = speed; // activate blending
loopModeBlendFrom = loopMode; blendTime = Math.min(blendTime, anim.getLength() / speed);
blendAmount = 0f; blendFrom = animation;
blendRate = 1f / blendTime; timeBlendFrom = time;
}else{ speedBlendFrom = speed;
blendFrom = null; loopModeBlendFrom = loopMode;
} blendAmount = 0f;
blendRate = 1f / blendTime;
animation = anim; }else{
time = 0; blendFrom = null;
speed = 1f; }
loopMode = LoopMode.Loop;
notified = false; animation = anim;
} time = 0;
speed = 1f;
/** loopMode = LoopMode.Loop;
* Set the current animation that is played by this AnimChannel. notified = false;
* <p> }
* See {@link #setAnim(java.lang.String, float)}.
* The blendTime argument by default is 150 milliseconds. /**
* * Set the current animation that is played by this AnimChannel.
* @param name The name of the animation to play * <p>
*/ * See {@link #setAnim(java.lang.String, float)}.
public void setAnim(String name){ * The blendTime argument by default is 150 milliseconds.
setAnim(name, DEFAULT_BLEND_TIME); *
} * @param name The name of the animation to play
*/
/** public void setAnim(String name){
* Add all the bones of the model's skeleton to be setAnim(name, DEFAULT_BLEND_TIME);
* influenced by this animation channel. }
*/
public void addAllBones() { /**
affectedBones = null; * Add all the bones of the model's skeleton to be
} * influenced by this animation channel.
*/
/** public void addAllBones() {
* Add a single bone to be influenced by this animation channel. affectedBones = null;
*/ }
public void addBone(String name) {
addBone(control.getSkeleton().getBone(name)); /**
} * Add a single bone to be influenced by this animation channel.
*/
/** public void addBone(String name) {
* Add a single bone to be influenced by this animation channel. addBone(control.getSkeleton().getBone(name));
*/ }
public void addBone(Bone bone) {
int boneIndex = control.getSkeleton().getBoneIndex(bone); /**
if(affectedBones == null) { * Add a single bone to be influenced by this animation channel.
affectedBones = new BitSet(control.getSkeleton().getBoneCount()); */
} public void addBone(Bone bone) {
affectedBones.set(boneIndex); int boneIndex = control.getSkeleton().getBoneIndex(bone);
} if(affectedBones == null) {
affectedBones = new BitSet(control.getSkeleton().getBoneCount());
/** }
* Add bones to be influenced by this animation channel starting from the affectedBones.set(boneIndex);
* given bone name and going toward the root bone. }
*/
public void addToRootBone(String name) { /**
addToRootBone(control.getSkeleton().getBone(name)); * Add bones to be influenced by this animation channel starting from the
} * given bone name and going toward the root bone.
*/
/** public void addToRootBone(String name) {
* Add bones to be influenced by this animation channel starting from the addToRootBone(control.getSkeleton().getBone(name));
* given bone and going toward the root bone. }
*/
public void addToRootBone(Bone bone) { /**
addBone(bone); * Add bones to be influenced by this animation channel starting from the
while (bone.getParent() != null) { * given bone and going toward the root bone.
bone = bone.getParent(); */
addBone(bone); public void addToRootBone(Bone bone) {
} addBone(bone);
} while (bone.getParent() != null) {
bone = bone.getParent();
/** addBone(bone);
* Add bones to be influenced by this animation channel, starting }
* from the given named bone and going toward its children. }
*/
public void addFromRootBone(String name) { /**
addFromRootBone(control.getSkeleton().getBone(name)); * Add bones to be influenced by this animation channel, starting
} * from the given named bone and going toward its children.
*/
/** public void addFromRootBone(String name) {
* Add bones to be influenced by this animation channel, starting addFromRootBone(control.getSkeleton().getBone(name));
* from the given bone and going toward its children. }
*/
public void addFromRootBone(Bone bone) { /**
addBone(bone); * Add bones to be influenced by this animation channel, starting
if (bone.getChildren() == null) * from the given bone and going toward its children.
return; */
for (Bone childBone : bone.getChildren()) { public void addFromRootBone(Bone bone) {
addBone(childBone); addBone(bone);
addFromRootBone(childBone); if (bone.getChildren() == null)
} return;
} for (Bone childBone : bone.getChildren()) {
addBone(childBone);
BitSet getAffectedBones(){ addFromRootBone(childBone);
return affectedBones; }
} }
public void reset(boolean rewind){ BitSet getAffectedBones(){
if(rewind){ return affectedBones;
setTime(0); }
if(control.getSkeleton()!=null){
control.getSkeleton().resetAndUpdate(); public void reset(boolean rewind){
}else{ if(rewind){
TempVars vars = TempVars.get(); setTime(0);
update(0, vars); if(control.getSkeleton()!=null){
vars.release(); control.getSkeleton().resetAndUpdate();
} }else{
} TempVars vars = TempVars.get();
animation = null; update(0, vars);
notified = false; vars.release();
} }
}
void update(float tpf, TempVars vars) { animation = null;
if (animation == null) notified = false;
return; }
if (blendFrom != null && blendAmount != 1.0f){ void update(float tpf, TempVars vars) {
// The blendFrom anim is set, the actual animation if (animation == null)
// playing will be set return;
// blendFrom.setTime(timeBlendFrom, 1f, control, this, vars);
blendFrom.setTime(timeBlendFrom, 1f - blendAmount, control, this, vars); if (blendFrom != null && blendAmount != 1.0f){
// The blendFrom anim is set, the actual animation
timeBlendFrom += tpf * speedBlendFrom; // playing will be set
timeBlendFrom = AnimationUtils.clampWrapTime(timeBlendFrom, // blendFrom.setTime(timeBlendFrom, 1f, control, this, vars);
blendFrom.getLength(), blendFrom.setTime(timeBlendFrom, 1f - blendAmount, control, this, vars);
loopModeBlendFrom);
if (timeBlendFrom < 0){ timeBlendFrom += tpf * speedBlendFrom;
timeBlendFrom = -timeBlendFrom; timeBlendFrom = AnimationUtils.clampWrapTime(timeBlendFrom,
speedBlendFrom = -speedBlendFrom; blendFrom.getLength(),
} loopModeBlendFrom);
if (timeBlendFrom < 0){
blendAmount += tpf * blendRate; timeBlendFrom = -timeBlendFrom;
if (blendAmount > 1f){ speedBlendFrom = -speedBlendFrom;
blendAmount = 1f; }
blendFrom = null;
} blendAmount += tpf * blendRate;
} if (blendAmount > 1f){
blendAmount = 1f;
animation.setTime(time, blendAmount, control, this, vars); blendFrom = null;
time += tpf * speed; }
if (animation.getLength() > 0){ }
if (!notified && (time >= animation.getLength() || time < 0)) {
if (loopMode == LoopMode.DontLoop) { animation.setTime(time, blendAmount, control, this, vars);
// Note that this flag has to be set before calling the notify time += tpf * speed;
// since the notify may start a new animation and then unset if (animation.getLength() > 0){
// the flag. if (!notified && (time >= animation.getLength() || time < 0)) {
notified = true; if (loopMode == LoopMode.DontLoop) {
} // Note that this flag has to be set before calling the notify
control.notifyAnimCycleDone(this, animation.getName()); // since the notify may start a new animation and then unset
} // the flag.
} notified = true;
time = AnimationUtils.clampWrapTime(time, animation.getLength(), loopMode); }
if (time < 0){ control.notifyAnimCycleDone(this, animation.getName());
// Negative time indicates that speed should be inverted }
// (for cycle loop mode only) }
time = -time; time = AnimationUtils.clampWrapTime(time, animation.getLength(), loopMode);
speed = -speed; if (time < 0){
} // Negative time indicates that speed should be inverted
} // (for cycle loop mode only)
} time = -time;
speed = -speed;
}
}
}

@ -41,7 +41,9 @@ import static com.jme3.animation.LoopMode.Loop;
*/ */
public class AnimationUtils { public class AnimationUtils {
public AnimationUtils(){
}
/** /**
* Clamps the time according to duration and loopMode * Clamps the time according to duration and loopMode
* @param time * @param time

File diff suppressed because it is too large Load Diff

@ -1,89 +1,93 @@
/* /*
* Copyright (c) 2009-2012 jMonkeyEngine * Copyright (c) 2009-2012 jMonkeyEngine
* All rights reserved. * All rights reserved.
* *
* Redistribution and use in source and binary forms, with or without * Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are * modification, are permitted provided that the following conditions are
* met: * met:
* *
* * Redistributions of source code must retain the above copyright * * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer. * notice, this list of conditions and the following disclaimer.
* *
* * Redistributions in binary form must reproduce the above copyright * * Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the * notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution. * documentation and/or other materials provided with the distribution.
* *
* * Neither the name of 'jMonkeyEngine' nor the names of its contributors * * Neither the name of 'jMonkeyEngine' nor the names of its contributors
* may be used to endorse or promote products derived from this software * may be used to endorse or promote products derived from this software
* without specific prior written permission. * without specific prior written permission.
* *
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
* TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
* PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/ */
package com.jme3.cinematic; package com.jme3.cinematic;
import com.jme3.cinematic.events.CinematicEvent; import com.jme3.cinematic.events.CinematicEvent;
import com.jme3.export.*; import com.jme3.export.*;
import java.io.IOException; import java.io.IOException;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.List; import java.util.List;
/** /**
* *
* @author Nehon * @author Nehon
*/ */
public class KeyFrame implements Savable { public class KeyFrame implements Savable {
List<CinematicEvent> cinematicEvents = new ArrayList<CinematicEvent>(); public KeyFrame(){
private int index;
}
public List<CinematicEvent> getCinematicEvents() {
return cinematicEvents; List<CinematicEvent> cinematicEvents = new ArrayList<>();
} private int index;
public void setCinematicEvents(List<CinematicEvent> cinematicEvents) { public List<CinematicEvent> getCinematicEvents() {
this.cinematicEvents = cinematicEvents; return cinematicEvents;
} }
public List<CinematicEvent> trigger() { public void setCinematicEvents(List<CinematicEvent> cinematicEvents) {
for (CinematicEvent event : cinematicEvents) { this.cinematicEvents = cinematicEvents;
event.play(); }
}
return cinematicEvents; public List<CinematicEvent> trigger() {
} for (CinematicEvent event : cinematicEvents) {
event.play();
public boolean isEmpty(){ }
return cinematicEvents.isEmpty(); return cinematicEvents;
} }
public void write(JmeExporter ex) throws IOException { public boolean isEmpty(){
OutputCapsule oc = ex.getCapsule(this); return cinematicEvents.isEmpty();
oc.writeSavableArrayList((ArrayList) cinematicEvents, "cinematicEvents", null); }
oc.write(index, "index", 0);
} public void write(JmeExporter ex) throws IOException {
OutputCapsule oc = ex.getCapsule(this);
public void read(JmeImporter im) throws IOException { oc.writeSavableArrayList((ArrayList) cinematicEvents, "cinematicEvents", null);
InputCapsule ic = im.getCapsule(this); oc.write(index, "index", 0);
cinematicEvents = ic.readSavableArrayList("cinematicEvents", null); }
index=ic.readInt("index", 0);
} public void read(JmeImporter im) throws IOException {
InputCapsule ic = im.getCapsule(this);
public int getIndex() { cinematicEvents = ic.readSavableArrayList("cinematicEvents", null);
return index; index=ic.readInt("index", 0);
} }
public void setIndex(int index) { public int getIndex() {
this.index = index; return index;
} }
public void setIndex(int index) {
} this.index = index;
}
}

@ -1,447 +1,448 @@
/* /*
* Copyright (c) 2009-2012 jMonkeyEngine * Copyright (c) 2009-2012 jMonkeyEngine
* All rights reserved. * All rights reserved.
* *
* Redistribution and use in source and binary forms, with or without * Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are * modification, are permitted provided that the following conditions are
* met: * met:
* *
* * Redistributions of source code must retain the above copyright * * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer. * notice, this list of conditions and the following disclaimer.
* *
* * Redistributions in binary form must reproduce the above copyright * * Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the * notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution. * documentation and/or other materials provided with the distribution.
* *
* * Neither the name of 'jMonkeyEngine' nor the names of its contributors * * Neither the name of 'jMonkeyEngine' nor the names of its contributors
* may be used to endorse or promote products derived from this software * may be used to endorse or promote products derived from this software
* without specific prior written permission. * without specific prior written permission.
* *
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
* TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
* PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/ */
package com.jme3.cinematic.events; package com.jme3.cinematic.events;
import com.jme3.animation.AnimChannel; import com.jme3.animation.AnimChannel;
import com.jme3.animation.AnimControl; import com.jme3.animation.AnimControl;
import com.jme3.animation.LoopMode; import com.jme3.animation.LoopMode;
import com.jme3.app.Application; import com.jme3.app.Application;
import com.jme3.cinematic.Cinematic; import com.jme3.cinematic.Cinematic;
import com.jme3.cinematic.PlayState; import com.jme3.cinematic.PlayState;
import com.jme3.export.InputCapsule; import com.jme3.export.InputCapsule;
import com.jme3.export.JmeExporter; 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.scene.Spatial; import com.jme3.scene.Spatial;
import java.io.IOException; import java.io.IOException;
import java.util.Collection; import java.util.Collection;
import java.util.HashMap; import java.util.HashMap;
import java.util.Map; import java.util.Map;
import java.util.logging.Logger; import java.util.logging.Logger;
/** /**
* An event based on an animation of a model. The model has to hold an * An event based on an animation of a model. The model has to hold an
* AnimControl with valid animation (bone or spatial animations). * AnimControl with valid animation (bone or spatial animations).
* *
* It helps to schedule the playback of an animation on a model in a Cinematic. * It helps to schedule the playback of an animation on a model in a Cinematic.
* *
* *
* @author Nehon * @author Nehon
*/ */
public class AnimationEvent extends AbstractCinematicEvent { public class AnimationEvent extends AbstractCinematicEvent {
// Version #2: directly keeping track on the model instead of trying to retrieve // Version #2: directly keeping track on the model instead of trying to retrieve
//it from the scene according to its name, because the name is not supposed to be unique //it from the scene according to its name, because the name is not supposed to be unique
//For backward compatibility, if the model is null it's looked up into the scene //For backward compatibility, if the model is null it's looked up into the scene
public static final int SAVABLE_VERSION = 2; public static final int SAVABLE_VERSION = 2;
private static final Logger log = Logger.getLogger(AnimationEvent.class.getName()); private static final Logger log = Logger.getLogger(AnimationEvent.class.getName());
public static final String MODEL_CHANNELS = "modelChannels"; public static final String MODEL_CHANNELS = "modelChannels";
protected AnimChannel channel; protected AnimChannel channel;
protected String animationName; protected String animationName;
protected Spatial model; protected Spatial model;
//kept for backward compatibility //kept for backward compatibility
protected String modelName; protected String modelName;
protected float blendTime = 0; protected float blendTime = 0;
protected int channelIndex = 0; protected int channelIndex = 0;
// parent cinematic // parent cinematic
protected Cinematic cinematic; protected Cinematic cinematic;
/** /**
* used for serialization don't call directly use one of the following * used for serialization don't call directly use one of the following
* constructors * constructors
*/ */
public AnimationEvent() { public AnimationEvent() {
} super();
}
/**
* creates an animation event /**
* * creates an animation event
* @param model the model on which the animation will be played *
* @param animationName the name of the animation to play * @param model the model on which the animation will be played
*/ * @param animationName the name of the animation to play
public AnimationEvent(Spatial model, String animationName) { */
this.model = model; public AnimationEvent(Spatial model, String animationName) {
this.animationName = animationName; this.model = model;
initialDuration = model.getControl(AnimControl.class).getAnimationLength(animationName); this.animationName = animationName;
} initialDuration = model.getControl(AnimControl.class).getAnimationLength(animationName);
}
/**
* creates an animation event /**
* * creates an animation event
* @param model the model on which the animation will be played *
* @param animationName the name of the animation to play * @param model the model on which the animation will be played
* @param initialDuration the initial duration of the event * @param animationName the name of the animation to play
*/ * @param initialDuration the initial duration of the event
public AnimationEvent(Spatial model, String animationName, float initialDuration) { */
super(initialDuration); public AnimationEvent(Spatial model, String animationName, float initialDuration) {
this.model = model; super(initialDuration);
this.animationName = animationName; this.model = model;
} this.animationName = animationName;
}
/**
* creates an animation event /**
* * creates an animation event
* @param model the model on which the animation will be played *
* @param animationName the name of the animation to play * @param model the model on which the animation will be played
* @param loopMode the loopMode * @param animationName the name of the animation to play
* @see LoopMode * @param loopMode the loopMode
*/ * @see LoopMode
public AnimationEvent(Spatial model, String animationName, LoopMode loopMode) { */
super(loopMode); public AnimationEvent(Spatial model, String animationName, LoopMode loopMode) {
initialDuration = model.getControl(AnimControl.class).getAnimationLength(animationName); super(loopMode);
this.model = model; initialDuration = model.getControl(AnimControl.class).getAnimationLength(animationName);
this.animationName = animationName; this.model = model;
} this.animationName = animationName;
}
/**
* creates an animation event /**
* * creates an animation event
* @param model the model on which the animation will be played *
* @param animationName the name of the animation to play * @param model the model on which the animation will be played
* @param initialDuration the initial duration of the event * @param animationName the name of the animation to play
* @param loopMode the loopMode * @param initialDuration the initial duration of the event
* @see LoopMode * @param loopMode the loopMode
*/ * @see LoopMode
public AnimationEvent(Spatial model, String animationName, float initialDuration, LoopMode loopMode) { */
super(initialDuration, loopMode); public AnimationEvent(Spatial model, String animationName, float initialDuration, LoopMode loopMode) {
this.model = model; super(initialDuration, loopMode);
this.animationName = animationName; this.model = model;
} this.animationName = animationName;
}
/**
* creates an animation event /**
* * creates an animation event
* @param model the model on which the animation will be played *
* @param animationName the name of the animation to play * @param model the model on which the animation will be played
* @param initialDuration the initial duration of the event * @param animationName the name of the animation to play
* @param blendTime the time during the animation are gonna be blended * @param initialDuration the initial duration of the event
* @see AnimChannel#setAnim(java.lang.String, float) * @param blendTime the time during the animation are gonna be blended
*/ * @see AnimChannel#setAnim(java.lang.String, float)
public AnimationEvent(Spatial model, String animationName, float initialDuration, float blendTime) { */
super(initialDuration); public AnimationEvent(Spatial model, String animationName, float initialDuration, float blendTime) {
this.model = model; super(initialDuration);
this.animationName = animationName; this.model = model;
this.blendTime = blendTime; this.animationName = animationName;
} this.blendTime = blendTime;
}
/**
* creates an animation event /**
* * creates an animation event
* @param model the model on which the animation will be played *
* @param animationName the name of the animation to play * @param model the model on which the animation will be played
* @param loopMode the loopMode * @param animationName the name of the animation to play
* @see LoopMode * @param loopMode the loopMode
* @param blendTime the time during the animation are gonna be blended * @see LoopMode
* @see AnimChannel#setAnim(java.lang.String, float) * @param blendTime the time during the animation are gonna be blended
*/ * @see AnimChannel#setAnim(java.lang.String, float)
public AnimationEvent(Spatial model, String animationName, LoopMode loopMode, float blendTime) { */
super(loopMode); public AnimationEvent(Spatial model, String animationName, LoopMode loopMode, float blendTime) {
initialDuration = model.getControl(AnimControl.class).getAnimationLength(animationName); super(loopMode);
this.model = model; initialDuration = model.getControl(AnimControl.class).getAnimationLength(animationName);
this.animationName = animationName; this.model = model;
this.blendTime = blendTime; this.animationName = animationName;
} this.blendTime = blendTime;
}
/**
* creates an animation event /**
* * creates an animation event
* @param model the model on which the animation will be played *
* @param animationName the name of the animation to play * @param model the model on which the animation will be played
* @param initialDuration the initial duration of the event * @param animationName the name of the animation to play
* @param loopMode the loopMode * @param initialDuration the initial duration of the event
* @see LoopMode * @param loopMode the loopMode
* @param blendTime the time during the animation are gonna be blended * @see LoopMode
* @see AnimChannel#setAnim(java.lang.String, float) * @param blendTime the time during the animation are gonna be blended
*/ * @see AnimChannel#setAnim(java.lang.String, float)
public AnimationEvent(Spatial model, String animationName, float initialDuration, LoopMode loopMode, float blendTime) { */
super(initialDuration, loopMode); public AnimationEvent(Spatial model, String animationName, float initialDuration, LoopMode loopMode, float blendTime) {
this.model = model; super(initialDuration, loopMode);
this.animationName = animationName; this.model = model;
this.blendTime = blendTime; this.animationName = animationName;
} this.blendTime = blendTime;
}
/**
* creates an animation event /**
* * creates an animation event
* @param model the model on which the animation will be played *
* @param animationName the name of the animation to play * @param model the model on which the animation will be played
* @param loopMode the loopMode * @param animationName the name of the animation to play
* @see LoopMode * @param loopMode the loopMode
* @param channelIndex the index of the channel default is 0. Events on the * @see LoopMode
* same channelIndex will use the same channel. * @param channelIndex the index of the channel default is 0. Events on the
*/ * same channelIndex will use the same channel.
public AnimationEvent(Spatial model, String animationName, LoopMode loopMode, int channelIndex) { */
super(loopMode); public AnimationEvent(Spatial model, String animationName, LoopMode loopMode, int channelIndex) {
initialDuration = model.getControl(AnimControl.class).getAnimationLength(animationName); super(loopMode);
this.model = model; initialDuration = model.getControl(AnimControl.class).getAnimationLength(animationName);
this.animationName = animationName; this.model = model;
this.channelIndex = channelIndex; this.animationName = animationName;
} this.channelIndex = channelIndex;
}
/**
* creates an animation event /**
* * creates an animation event
* @param model the model on which the animation will be played *
* @param animationName the name of the animation to play * @param model the model on which the animation will be played
* @param channelIndex the index of the channel default is 0. Events on the * @param animationName the name of the animation to play
* same channelIndex will use the same channel. * @param channelIndex the index of the channel default is 0. Events on the
*/ * same channelIndex will use the same channel.
public AnimationEvent(Spatial model, String animationName, int channelIndex) { */
this.model = model; public AnimationEvent(Spatial model, String animationName, int channelIndex) {
this.animationName = animationName; this.model = model;
initialDuration = model.getControl(AnimControl.class).getAnimationLength(animationName); this.animationName = animationName;
this.channelIndex = channelIndex; initialDuration = model.getControl(AnimControl.class).getAnimationLength(animationName);
} this.channelIndex = channelIndex;
}
/**
* creates an animation event /**
* * creates an animation event
* @param model the model on which the animation will be played *
* @param animationName the name of the animation to play * @param model the model on which the animation will be played
* @param channelIndex the index of the channel default is 0. Events on the * @param animationName the name of the animation to play
* @param blendTime the time during the animation are gonna be blended * @param channelIndex the index of the channel default is 0. Events on the
* same channelIndex will use the same channel. * @param blendTime the time during the animation are gonna be blended
*/ * same channelIndex will use the same channel.
public AnimationEvent(Spatial model, String animationName, LoopMode loopMode, int channelIndex, float blendTime) { */
this.model = model; public AnimationEvent(Spatial model, String animationName, LoopMode loopMode, int channelIndex, float blendTime) {
this.animationName = animationName; this.model = model;
this.loopMode = loopMode; this.animationName = animationName;
initialDuration = model.getControl(AnimControl.class).getAnimationLength(animationName); this.loopMode = loopMode;
this.channelIndex = channelIndex; initialDuration = model.getControl(AnimControl.class).getAnimationLength(animationName);
this.blendTime = blendTime; this.channelIndex = channelIndex;
} this.blendTime = blendTime;
}
/**
* creates an animation event /**
* * creates an animation event
* @param model the model on which the animation will be played *
* @param animationName the name of the animation to play * @param model the model on which the animation will be played
* @param initialDuration the initial duration of the event * @param animationName the name of the animation to play
* @param channelIndex the index of the channel default is 0. Events on the * @param initialDuration the initial duration of the event
* same channelIndex will use the same channel. * @param channelIndex the index of the channel default is 0. Events on the
*/ * same channelIndex will use the same channel.
public AnimationEvent(Spatial model, String animationName, float initialDuration, int channelIndex) { */
super(initialDuration); public AnimationEvent(Spatial model, String animationName, float initialDuration, int channelIndex) {
this.model = model; super(initialDuration);
this.animationName = animationName; this.model = model;
this.channelIndex = channelIndex; this.animationName = animationName;
} this.channelIndex = channelIndex;
}
/**
* creates an animation event /**
* * creates an animation event
* @param model the model on which the animation will be played *
* @param animationName the name of the animation to play * @param model the model on which the animation will be played
* @param initialDuration the initial duration of the event * @param animationName the name of the animation to play
* @param loopMode the loopMode * @param initialDuration the initial duration of the event
* @see LoopMode * @param loopMode the loopMode
* @param channelIndex the index of the channel default is 0. Events on the * @see LoopMode
* same channelIndex will use the same channel. * @param channelIndex the index of the channel default is 0. Events on the
*/ * same channelIndex will use the same channel.
public AnimationEvent(Spatial model, String animationName, float initialDuration, LoopMode loopMode, int channelIndex) { */
super(initialDuration, loopMode); public AnimationEvent(Spatial model, String animationName, float initialDuration, LoopMode loopMode, int channelIndex) {
this.model = model; super(initialDuration, loopMode);
this.animationName = animationName; this.model = model;
this.channelIndex = channelIndex; this.animationName = animationName;
} this.channelIndex = channelIndex;
}
@Override
public void initEvent(Application app, Cinematic cinematic) { @Override
super.initEvent(app, cinematic); public void initEvent(Application app, Cinematic cinematic) {
this.cinematic = cinematic; super.initEvent(app, cinematic);
if (channel == null) { this.cinematic = cinematic;
Object s = cinematic.getEventData(MODEL_CHANNELS, model); if (channel == null) {
if (s == null) { Object s = cinematic.getEventData(MODEL_CHANNELS, model);
s = new HashMap<Integer, AnimChannel>(); if (s == null) {
int numChannels = model.getControl(AnimControl.class).getNumChannels(); s = new HashMap<Integer, AnimChannel>();
for(int i = 0; i < numChannels; i++){ int numChannels = model.getControl(AnimControl.class).getNumChannels();
((HashMap<Integer, AnimChannel>)s).put(i, model.getControl(AnimControl.class).getChannel(i)); for(int i = 0; i < numChannels; i++){
} ((HashMap<Integer, AnimChannel>)s).put(i, model.getControl(AnimControl.class).getChannel(i));
cinematic.putEventData(MODEL_CHANNELS, model, s); }
} cinematic.putEventData(MODEL_CHANNELS, model, s);
}
Map<Integer, AnimChannel> map = (Map<Integer, AnimChannel>) s;
this.channel = map.get(channelIndex); Map<Integer, AnimChannel> map = (Map<Integer, AnimChannel>) s;
if (this.channel == null) { this.channel = map.get(channelIndex);
if (model == null) { if (this.channel == null) {
//the model is null we try to find it according to the name if (model == null) {
//this should occur only when loading an old saved cinematic //the model is null we try to find it according to the name
//othewise it's an error //this should occur only when loading an old saved cinematic
model = cinematic.getScene().getChild(modelName); //othewise it's an error
} model = cinematic.getScene().getChild(modelName);
if (model != null) { }
channel = model.getControl(AnimControl.class).createChannel(); if (model != null) {
map.put(channelIndex, channel); channel = model.getControl(AnimControl.class).createChannel();
} else { map.put(channelIndex, channel);
//it's an error } else {
throw new UnsupportedOperationException("model should not be null"); //it's an error
} throw new UnsupportedOperationException("model should not be null");
} }
}
}
} }
}
@Override
public void setTime(float time) { @Override
super.setTime(time); public void setTime(float time) {
if (!animationName.equals(channel.getAnimationName())) { super.setTime(time);
channel.setAnim(animationName, blendTime); if (!animationName.equals(channel.getAnimationName())) {
} channel.setAnim(animationName, blendTime);
float t = time; }
if (loopMode == loopMode.Loop) { float t = time;
t = t % channel.getAnimMaxTime(); if (loopMode == loopMode.Loop) {
} t = t % channel.getAnimMaxTime();
if (loopMode == loopMode.Cycle) { }
float parity = (float) Math.ceil(time / channel.getAnimMaxTime()); if (loopMode == loopMode.Cycle) {
if (parity > 0 && parity % 2 == 0) { float parity = (float) Math.ceil(time / channel.getAnimMaxTime());
t = channel.getAnimMaxTime() - t % channel.getAnimMaxTime(); if (parity > 0 && parity % 2 == 0) {
} else { t = channel.getAnimMaxTime() - t % channel.getAnimMaxTime();
t = t % channel.getAnimMaxTime(); } else {
} t = t % channel.getAnimMaxTime();
}
}
if (t < 0) { }
channel.setTime(0); if (t < 0) {
channel.reset(true); channel.setTime(0);
} channel.reset(true);
if (t > channel.getAnimMaxTime()) { }
channel.setTime(t); if (t > channel.getAnimMaxTime()) {
channel.getControl().update(0); channel.setTime(t);
stop(); channel.getControl().update(0);
} else { stop();
channel.setTime(t); } else {
channel.getControl().update(0); channel.setTime(t);
} channel.getControl().update(0);
}
}
}
@Override
public void onPlay() { @Override
channel.getControl().setEnabled(true); public void onPlay() {
if (playState == PlayState.Stopped) { channel.getControl().setEnabled(true);
channel.setAnim(animationName, blendTime); if (playState == PlayState.Stopped) {
channel.setSpeed(speed); channel.setAnim(animationName, blendTime);
channel.setLoopMode(loopMode); channel.setSpeed(speed);
channel.setTime(0); channel.setLoopMode(loopMode);
} channel.setTime(0);
} }
}
@Override
public void setSpeed(float speed) { @Override
super.setSpeed(speed); public void setSpeed(float speed) {
if (channel != null) { super.setSpeed(speed);
channel.setSpeed(speed); if (channel != null) {
} channel.setSpeed(speed);
} }
}
@Override
public void onUpdate(float tpf) { @Override
} public void onUpdate(float tpf) {
}
@Override
public void onStop() { @Override
} public void onStop() {
}
@Override
public void forceStop() { @Override
if (channel != null) { public void forceStop() {
channel.setTime(time); if (channel != null) {
channel.reset(false); channel.setTime(time);
} channel.reset(false);
super.forceStop(); }
} super.forceStop();
}
@Override
public void onPause() { @Override
if (channel != null) { public void onPause() {
channel.getControl().setEnabled(false); if (channel != null) {
} channel.getControl().setEnabled(false);
} }
}
@Override
public void setLoopMode(LoopMode loopMode) { @Override
super.setLoopMode(loopMode); public void setLoopMode(LoopMode loopMode) {
if (channel != null) { super.setLoopMode(loopMode);
channel.setLoopMode(loopMode); if (channel != null) {
} channel.setLoopMode(loopMode);
} }
}
@Override
public void write(JmeExporter ex) throws IOException { @Override
super.write(ex); public void write(JmeExporter ex) throws IOException {
OutputCapsule oc = ex.getCapsule(this); super.write(ex);
OutputCapsule oc = ex.getCapsule(this);
oc.write(model, "model", null);
oc.write(animationName, "animationName", ""); oc.write(model, "model", null);
oc.write(blendTime, "blendTime", 0f); oc.write(animationName, "animationName", "");
oc.write(channelIndex, "channelIndex", 0); oc.write(blendTime, "blendTime", 0f);
oc.write(channelIndex, "channelIndex", 0);
}
}
@Override
public void read(JmeImporter im) throws IOException { @Override
super.read(im); public void read(JmeImporter im) throws IOException {
InputCapsule ic = im.getCapsule(this); super.read(im);
if (im.getFormatVersion() == 0) { InputCapsule ic = im.getCapsule(this);
modelName = ic.readString("modelName", ""); if (im.getFormatVersion() == 0) {
} modelName = ic.readString("modelName", "");
//FIXME always the same issue, because of the clonning of assets, this won't work }
//we have to somehow store userdata in the spatial and then recurse the //FIXME always the same issue, because of the clonning of assets, this won't work
//scene sub scenegraph to find the correct instance of the model //we have to somehow store userdata in the spatial and then recurse the
//This brings a reflaxion about the cinematic being an appstate, //scene sub scenegraph to find the correct instance of the model
//shouldn't it be a control over the scene //This brings a reflaxion about the cinematic being an appstate,
// this would allow to use the cloneForSpatial method and automatically //shouldn't it be a control over the scene
//rebind cloned references of original objects. // this would allow to use the cloneForSpatial method and automatically
//for now as nobody probably ever saved a cinematic, this is not a critical issue //rebind cloned references of original objects.
model = (Spatial) ic.readSavable("model", null); //for now as nobody probably ever saved a cinematic, this is not a critical issue
animationName = ic.readString("animationName", ""); model = (Spatial) ic.readSavable("model", null);
blendTime = ic.readFloat("blendTime", 0f); animationName = ic.readString("animationName", "");
channelIndex = ic.readInt("channelIndex", 0); blendTime = ic.readFloat("blendTime", 0f);
} channelIndex = ic.readInt("channelIndex", 0);
}
@Override
public void dispose() { @Override
super.dispose(); public void dispose() {
if (cinematic != null) { super.dispose();
Object o = cinematic.getEventData(MODEL_CHANNELS, model); if (cinematic != null) {
if (o != null) { Object o = cinematic.getEventData(MODEL_CHANNELS, model);
Collection<AnimChannel> values = ((HashMap<Integer, AnimChannel>) o).values(); if (o != null) {
while (values.remove(channel)); Collection<AnimChannel> values = ((HashMap<Integer, AnimChannel>) o).values();
if (values.isEmpty()) { while (values.remove(channel));
cinematic.removeEventData(MODEL_CHANNELS, model); if (values.isEmpty()) {
} cinematic.removeEventData(MODEL_CHANNELS, model);
} }
cinematic = null; }
channel = null; cinematic = null;
} channel = null;
} }
} }
}

@ -0,0 +1,146 @@
/*
* Copyright (c) 2009-2017 jMonkeyEngine
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are
* met:
*
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
*
* * Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* * Neither the name of 'jMonkeyEngine' nor the names of its contributors
* may be used to endorse or promote products derived from this software
* without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
* TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
* PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
package com.jme3.cinematic.events;
import com.jme3.app.Application;
import com.jme3.cinematic.Cinematic;
import com.jme3.cinematic.TimeLine;
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.scene.CameraNode;
import java.io.IOException;
import java.util.Map;
/**
*
* @author Rickard <neph1 @ github>
*/
public class CameraEvent extends AbstractCinematicEvent{
private String cameraName;
private Cinematic cinematic;
public String getCameraName() {
return cameraName;
}
public void setCameraName(String cameraName) {
this.cameraName = cameraName;
}
public CameraEvent(){
}
public CameraEvent(Cinematic parentEvent, String cameraName){
this.cinematic = parentEvent;
this.cameraName = cameraName;
}
@Override
public void initEvent(Application app, Cinematic cinematic) {
super.initEvent(app, cinematic);
this.cinematic = cinematic;
}
@Override
public void play() {
super.play();
stop();
}
@Override
public void onPlay() {
cinematic.setActiveCamera(cameraName);
}
@Override
public void onUpdate(float tpf) {
}
@Override
public void onStop() {
}
@Override
public void onPause() {
}
@Override
public void forceStop() {
}
@Override
public void setTime(float time) {
play();
}
public Cinematic getCinematic() {
return cinematic;
}
public void setCinematic(Cinematic cinematic) {
this.cinematic = cinematic;
}
/**
* used internally for serialization
*
* @param ex
* @throws IOException
*/
@Override
public void write(JmeExporter ex) throws IOException {
super.write(ex);
OutputCapsule oc = ex.getCapsule(this);
oc.write(cameraName, "cameraName", null);
}
/**
* used internally for serialization
*
* @param im
* @throws IOException
*/
@Override
public void read(JmeImporter im) throws IOException {
super.read(im);
InputCapsule ic = im.getCapsule(this);
cameraName = ic.readString("cameraName", null);
}
}

@ -1,491 +1,491 @@
/* /*
* Copyright (c) 2009-2016 jMonkeyEngine * Copyright (c) 2009-2016 jMonkeyEngine
* All rights reserved. * All rights reserved.
* *
* Redistribution and use in source and binary forms, with or without * Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are * modification, are permitted provided that the following conditions are
* met: * met:
* *
* * Redistributions of source code must retain the above copyright * * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer. * notice, this list of conditions and the following disclaimer.
* *
* * Redistributions in binary form must reproduce the above copyright * * Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the * notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution. * documentation and/or other materials provided with the distribution.
* *
* * Neither the name of 'jMonkeyEngine' nor the names of its contributors * * Neither the name of 'jMonkeyEngine' nor the names of its contributors
* may be used to endorse or promote products derived from this software * may be used to endorse or promote products derived from this software
* without specific prior written permission. * without specific prior written permission.
* *
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
* TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
* PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/ */
package com.jme3.cinematic.events; package com.jme3.cinematic.events;
import com.jme3.animation.AnimationUtils; import com.jme3.animation.AnimationUtils;
import com.jme3.animation.LoopMode; import com.jme3.animation.LoopMode;
import com.jme3.app.Application; import com.jme3.app.Application;
import com.jme3.cinematic.Cinematic; import com.jme3.cinematic.Cinematic;
import com.jme3.cinematic.MotionPath; import com.jme3.cinematic.MotionPath;
import com.jme3.cinematic.PlayState; import com.jme3.cinematic.PlayState;
import com.jme3.export.InputCapsule; import com.jme3.export.InputCapsule;
import com.jme3.export.JmeExporter; 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.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.clone.Cloner; import com.jme3.util.clone.Cloner;
import com.jme3.util.clone.JmeCloneable; import com.jme3.util.clone.JmeCloneable;
import java.io.IOException; import java.io.IOException;
/** /**
* A MotionEvent is a control over the spatial that manages the position and direction of the spatial while following a motion Path. * A MotionEvent is a control over the spatial that manages the position and direction of the spatial while following a motion Path.
* *
* You must first create a MotionPath and then create a MotionEvent to associate a spatial and the path. * You must first create a MotionPath and then create a MotionEvent to associate a spatial and the path.
* *
* @author Nehon * @author Nehon
*/ */
public class MotionEvent extends AbstractCinematicEvent implements Control, JmeCloneable { public class MotionEvent extends AbstractCinematicEvent implements Control, JmeCloneable {
protected Spatial spatial; protected Spatial spatial;
protected int currentWayPoint; protected int currentWayPoint;
protected float currentValue; protected float currentValue;
protected Vector3f direction = new Vector3f(); protected Vector3f direction = new Vector3f();
protected Vector3f lookAt = null; protected Vector3f lookAt = null;
protected Vector3f upVector = Vector3f.UNIT_Y; protected Vector3f upVector = Vector3f.UNIT_Y;
protected Quaternion rotation = null; protected Quaternion rotation = null;
protected Direction directionType = Direction.None; protected Direction directionType = Direction.None;
protected MotionPath path; protected MotionPath path;
private boolean isControl = true; private boolean isControl = true;
private int travelDirection = 1; private int travelDirection = 1;
/** /**
* the distance traveled by the spatial on the path * the distance traveled by the spatial on the path
*/ */
protected float traveledDistance = 0; protected float traveledDistance = 0;
/** /**
* Enum for the different type of target direction behavior. * Enum for the different type of target direction behavior.
*/ */
public enum Direction { public enum Direction {
/** /**
* The target stays in the starting direction. * The target stays in the starting direction.
*/ */
None, None,
/** /**
* The target rotates with the direction of the path. * The target rotates with the direction of the path.
*/ */
Path, Path,
/** /**
* The target rotates with the direction of the path but with the addition of a rotation. * The target rotates with the direction of the path but with the addition of a rotation.
* You need to use the setRotation method when using this Direction. * You need to use the setRotation method when using this Direction.
*/ */
PathAndRotation, PathAndRotation,
/** /**
* The target rotates with the given rotation. * The target rotates with the given rotation.
*/ */
Rotation, Rotation,
/** /**
* The target looks at a point. * The target looks at a point.
* You need to use the setLookAt method when using this direction. * You need to use the setLookAt method when using this direction.
*/ */
LookAt LookAt
} }
/** /**
* Create MotionEvent, * Create MotionEvent,
* when using this constructor don't forget to assign spatial and path. * when using this constructor don't forget to assign spatial and path.
*/ */
public MotionEvent() { public MotionEvent() {
super(); super();
} }
/** /**
* Creates a MotionPath for the given spatial on the given motion path. * Creates a MotionPath for the given spatial on the given motion path.
* @param spatial * @param spatial
* @param path * @param path
*/ */
public MotionEvent(Spatial spatial, MotionPath path) { public MotionEvent(Spatial spatial, MotionPath path) {
super(); super();
spatial.addControl(this); spatial.addControl(this);
this.path = path; this.path = path;
} }
/** /**
* Creates a MotionPath for the given spatial on the given motion path. * Creates a MotionPath for the given spatial on the given motion path.
* @param spatial * @param spatial
* @param path * @param path
*/ */
public MotionEvent(Spatial spatial, MotionPath path, float initialDuration) { public MotionEvent(Spatial spatial, MotionPath path, float initialDuration) {
super(initialDuration); super(initialDuration);
spatial.addControl(this); spatial.addControl(this);
this.path = path; this.path = path;
} }
/** /**
* Creates a MotionPath for the given spatial on the given motion path. * Creates a MotionPath for the given spatial on the given motion path.
* @param spatial * @param spatial
* @param path * @param path
*/ */
public MotionEvent(Spatial spatial, MotionPath path, LoopMode loopMode) { public MotionEvent(Spatial spatial, MotionPath path, LoopMode loopMode) {
super(); super();
spatial.addControl(this); spatial.addControl(this);
this.path = path; this.path = path;
this.loopMode = loopMode; this.loopMode = loopMode;
} }
/** /**
* Creates a MotionPath for the given spatial on the given motion path. * Creates a MotionPath for the given spatial on the given motion path.
* @param spatial * @param spatial
* @param path * @param path
*/ */
public MotionEvent(Spatial spatial, MotionPath path, float initialDuration, LoopMode loopMode) { public MotionEvent(Spatial spatial, MotionPath path, float initialDuration, LoopMode loopMode) {
super(initialDuration); super(initialDuration);
spatial.addControl(this); spatial.addControl(this);
this.path = path; this.path = path;
this.loopMode = loopMode; this.loopMode = loopMode;
} }
public void update(float tpf) { public void update(float tpf) {
if (isControl) { if (isControl) {
internalUpdate(tpf); internalUpdate(tpf);
} }
} }
@Override @Override
public void internalUpdate(float tpf) { public void internalUpdate(float tpf) {
if (playState == PlayState.Playing) { if (playState == PlayState.Playing) {
time = time + (tpf * speed); time = time + (tpf * speed);
if (loopMode == LoopMode.Loop && time < 0) { if (loopMode == LoopMode.Loop && time < 0) {
time = initialDuration; time = initialDuration;
} }
if ((time >= initialDuration || time < 0) && loopMode == LoopMode.DontLoop) { if ((time >= initialDuration || time < 0) && loopMode == LoopMode.DontLoop) {
if (time >= initialDuration) { if (time >= initialDuration) {
path.triggerWayPointReach(path.getNbWayPoints() - 1, this); path.triggerWayPointReach(path.getNbWayPoints() - 1, this);
} }
stop(); stop();
} else { } else {
time = AnimationUtils.clampWrapTime(time, initialDuration, loopMode); time = AnimationUtils.clampWrapTime(time, initialDuration, loopMode);
if(time<0){ if(time<0){
speed = - speed; speed = - speed;
time = - time; time = - time;
} }
onUpdate(tpf); onUpdate(tpf);
} }
} }
} }
@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;
} }
@Override @Override
public void setTime(float time) { public void setTime(float time) {
super.setTime(time); super.setTime(time);
onUpdate(0); onUpdate(0);
} }
public void onUpdate(float tpf) { public void onUpdate(float tpf) {
traveledDistance = path.interpolatePath(time, this, tpf); traveledDistance = path.interpolatePath(time, this, tpf);
computeTargetDirection(); computeTargetDirection();
} }
@Override @Override
public void write(JmeExporter ex) throws IOException { public void write(JmeExporter ex) throws IOException {
super.write(ex); super.write(ex);
OutputCapsule oc = ex.getCapsule(this); OutputCapsule oc = ex.getCapsule(this);
oc.write(lookAt, "lookAt", null); oc.write(lookAt, "lookAt", null);
oc.write(upVector, "upVector", Vector3f.UNIT_Y); oc.write(upVector, "upVector", Vector3f.UNIT_Y);
oc.write(rotation, "rotation", null); oc.write(rotation, "rotation", null);
oc.write(directionType, "directionType", Direction.None); oc.write(directionType, "directionType", Direction.None);
oc.write(path, "path", null); oc.write(path, "path", null);
oc.write(spatial, "spatial", null); oc.write(spatial, "spatial", null);
} }
@Override @Override
public void read(JmeImporter im) throws IOException { public void read(JmeImporter im) throws IOException {
super.read(im); super.read(im);
InputCapsule in = im.getCapsule(this); InputCapsule in = im.getCapsule(this);
lookAt = (Vector3f) in.readSavable("lookAt", null); lookAt = (Vector3f) in.readSavable("lookAt", null);
upVector = (Vector3f) in.readSavable("upVector", Vector3f.UNIT_Y); upVector = (Vector3f) in.readSavable("upVector", Vector3f.UNIT_Y);
rotation = (Quaternion) in.readSavable("rotation", null); rotation = (Quaternion) in.readSavable("rotation", null);
directionType = in.readEnum("directionType", Direction.class, Direction.None); directionType = in.readEnum("directionType", Direction.class, Direction.None);
path = (MotionPath) in.readSavable("path", null); path = (MotionPath) in.readSavable("path", null);
spatial = (Spatial) in.readSavable("spatial", null); spatial = (Spatial) in.readSavable("spatial", null);
} }
/** /**
* This method is meant to be called by the motion path only. * This method is meant to be called by the motion path only.
* @return * @return
*/ */
public boolean needsDirection() { public boolean needsDirection() {
return directionType == Direction.Path || directionType == Direction.PathAndRotation; return directionType == Direction.Path || directionType == Direction.PathAndRotation;
} }
private void computeTargetDirection() { private void computeTargetDirection() {
switch (directionType) { switch (directionType) {
case Path: case Path:
Quaternion q = new Quaternion(); Quaternion q = new Quaternion();
q.lookAt(direction, upVector); q.lookAt(direction, upVector);
spatial.setLocalRotation(q); spatial.setLocalRotation(q);
break; break;
case LookAt: case LookAt:
if (lookAt != null) { if (lookAt != null) {
spatial.lookAt(lookAt, upVector); spatial.lookAt(lookAt, upVector);
} }
break; break;
case PathAndRotation: case PathAndRotation:
if (rotation != null) { if (rotation != null) {
Quaternion q2 = new Quaternion(); Quaternion q2 = new Quaternion();
q2.lookAt(direction, upVector); q2.lookAt(direction, upVector);
q2.multLocal(rotation); q2.multLocal(rotation);
spatial.setLocalRotation(q2); spatial.setLocalRotation(q2);
} }
break; break;
case Rotation: case Rotation:
if (rotation != null) { if (rotation != null) {
spatial.setLocalRotation(rotation); spatial.setLocalRotation(rotation);
} }
break; break;
case None: case None:
break; break;
default: default:
break; break;
} }
} }
/** /**
* Clone this control for the given spatial. * Clone this control for the given spatial.
* @param spatial * @param spatial
* @return * @return
*/ */
@Override @Override
public Control cloneForSpatial(Spatial spatial) { public Control cloneForSpatial(Spatial spatial) {
MotionEvent control = new MotionEvent(); MotionEvent control = new MotionEvent();
control.setPath(path); control.setPath(path);
control.playState = playState; control.playState = playState;
control.currentWayPoint = currentWayPoint; control.currentWayPoint = currentWayPoint;
control.currentValue = currentValue; control.currentValue = currentValue;
control.direction = direction.clone(); control.direction = direction.clone();
control.lookAt = lookAt; control.lookAt = lookAt;
control.upVector = upVector.clone(); control.upVector = upVector.clone();
control.rotation = rotation; control.rotation = rotation;
control.initialDuration = initialDuration; control.initialDuration = initialDuration;
control.speed = speed; control.speed = speed;
control.loopMode = loopMode; control.loopMode = loopMode;
control.directionType = directionType; control.directionType = directionType;
return control; return control;
} }
@Override @Override
public Object jmeClone() { public Object jmeClone() {
MotionEvent control = new MotionEvent(); MotionEvent control = new MotionEvent();
control.path = path; control.path = path;
control.playState = playState; control.playState = playState;
control.currentWayPoint = currentWayPoint; control.currentWayPoint = currentWayPoint;
control.currentValue = currentValue; control.currentValue = currentValue;
control.direction = direction.clone(); control.direction = direction.clone();
control.lookAt = lookAt; control.lookAt = lookAt;
control.upVector = upVector.clone(); control.upVector = upVector.clone();
control.rotation = rotation; control.rotation = rotation;
control.initialDuration = initialDuration; control.initialDuration = initialDuration;
control.speed = speed; control.speed = speed;
control.loopMode = loopMode; control.loopMode = loopMode;
control.directionType = directionType; control.directionType = directionType;
control.spatial = spatial; control.spatial = spatial;
return control; return control;
} }
@Override @Override
public void cloneFields( Cloner cloner, Object original ) { public void cloneFields( Cloner cloner, Object original ) {
this.spatial = cloner.clone(spatial); this.spatial = cloner.clone(spatial);
} }
@Override @Override
public void onPlay() { public void onPlay() {
traveledDistance = 0; traveledDistance = 0;
} }
@Override @Override
public void onStop() { public void onStop() {
currentWayPoint = 0; currentWayPoint = 0;
} }
@Override @Override
public void onPause() { public void onPause() {
} }
/** /**
* This method is meant to be called by the motion path only. * This method is meant to be called by the motion path only.
* @return * @return
*/ */
public float getCurrentValue() { public float getCurrentValue() {
return currentValue; return currentValue;
} }
/** /**
* This method is meant to be called by the motion path only. * This method is meant to be called by the motion path only.
* *
*/ */
public void setCurrentValue(float currentValue) { public void setCurrentValue(float currentValue) {
this.currentValue = currentValue; this.currentValue = currentValue;
} }
/** /**
* This method is meant to be called by the motion path only. * This method is meant to be called by the motion path only.
* @return * @return
*/ */
public int getCurrentWayPoint() { public int getCurrentWayPoint() {
return currentWayPoint; return currentWayPoint;
} }
/** /**
* This method is meant to be called by the motion path only. * This method is meant to be called by the motion path only.
* *
*/ */
public void setCurrentWayPoint(int currentWayPoint) { public void setCurrentWayPoint(int currentWayPoint) {
this.currentWayPoint = currentWayPoint; this.currentWayPoint = currentWayPoint;
} }
/** /**
* Returns the direction the spatial is moving. * Returns the direction the spatial is moving.
* @return * @return
*/ */
public Vector3f getDirection() { public Vector3f getDirection() {
return direction; return direction;
} }
/** /**
* Sets the direction of the spatial, using the Y axis as the up vector. * Sets the direction of the spatial, using the Y axis as the up vector.
* Use MotionEvent#setDirection((Vector3f direction,Vector3f upVector) if * Use MotionEvent#setDirection((Vector3f direction,Vector3f upVector) if
* you want a custum up vector. * you want a custum up vector.
* This method is used by the motion path. * This method is used by the motion path.
* @param direction * @param direction
*/ */
public void setDirection(Vector3f direction) { public void setDirection(Vector3f direction) {
setDirection(direction, Vector3f.UNIT_Y); setDirection(direction, Vector3f.UNIT_Y);
} }
/** /**
* Sets the direction of the spatial with the given up vector. * Sets the direction of the spatial with the given up vector.
* This method is used by the motion path. * This method is used by the motion path.
* @param direction * @param direction
* @param upVector the up vector to consider for this direction. * @param upVector the up vector to consider for this direction.
*/ */
public void setDirection(Vector3f direction,Vector3f upVector) { public void setDirection(Vector3f direction,Vector3f upVector) {
this.direction.set(direction); this.direction.set(direction);
this.upVector.set(upVector); this.upVector.set(upVector);
} }
/** /**
* Returns the direction type of the target. * Returns the direction type of the target.
* @return the direction type. * @return the direction type.
*/ */
public Direction getDirectionType() { public Direction getDirectionType() {
return directionType; return directionType;
} }
/** /**
* Sets the direction type of the target. * Sets the direction type of the target.
* On each update the direction given to the target can have different behavior. * On each update the direction given to the target can have different behavior.
* See the Direction Enum for explanations. * See the Direction Enum for explanations.
* @param directionType the direction type. * @param directionType the direction type.
*/ */
public void setDirectionType(Direction directionType) { public void setDirectionType(Direction directionType) {
this.directionType = directionType; this.directionType = directionType;
} }
/** /**
* Set the lookAt for the target. * Set the lookAt for the target.
* This can be used only if direction Type is Direction.LookAt. * This can be used only if direction Type is Direction.LookAt.
* @param lookAt the position to look at. * @param lookAt the position to look at.
* @param upVector the up vector. * @param upVector the up vector.
*/ */
public void setLookAt(Vector3f lookAt, Vector3f upVector) { public void setLookAt(Vector3f lookAt, Vector3f upVector) {
this.lookAt = lookAt; this.lookAt = lookAt;
this.upVector = upVector; this.upVector = upVector;
} }
/** /**
* Returns the rotation of the target. * Returns the rotation of the target.
* @return the rotation quaternion. * @return the rotation quaternion.
*/ */
public Quaternion getRotation() { public Quaternion getRotation() {
return rotation; return rotation;
} }
/** /**
* Sets the rotation of the target. * Sets the rotation of the target.
* This can be used only if direction Type is Direction.PathAndRotation or Direction.Rotation. * This can be used only if direction Type is Direction.PathAndRotation or Direction.Rotation.
* With PathAndRotation the target will face the direction of the path multiplied by the given Quaternion. * With PathAndRotation the target will face the direction of the path multiplied by the given Quaternion.
* With Rotation the rotation of the target will be set with the given Quaternion. * With Rotation the rotation of the target will be set with the given Quaternion.
* @param rotation the rotation quaternion. * @param rotation the rotation quaternion.
*/ */
public void setRotation(Quaternion rotation) { public void setRotation(Quaternion rotation) {
this.rotation = rotation; this.rotation = rotation;
} }
/** /**
* Return the motion path this control follows. * Return the motion path this control follows.
* @return * @return
*/ */
public MotionPath getPath() { public MotionPath getPath() {
return path; return path;
} }
/** /**
* Sets the motion path to follow. * Sets the motion path to follow.
* @param path * @param path
*/ */
public void setPath(MotionPath path) { public void setPath(MotionPath path) {
this.path = path; this.path = path;
} }
public void setEnabled(boolean enabled) { public void setEnabled(boolean enabled) {
if (enabled) { if (enabled) {
play(); play();
} else { } else {
pause(); pause();
} }
} }
public boolean isEnabled() { public boolean isEnabled() {
return playState != PlayState.Stopped; return playState != PlayState.Stopped;
} }
public void render(RenderManager rm, ViewPort vp) { public void render(RenderManager rm, ViewPort vp) {
} }
public void setSpatial(Spatial spatial) { public void setSpatial(Spatial spatial) {
this.spatial = spatial; this.spatial = spatial;
} }
public Spatial getSpatial() { public Spatial getSpatial() {
return spatial; return spatial;
} }
/** /**
* Return the distance traveled by the spatial on the path. * Return the distance traveled by the spatial on the path.
* @return * @return
*/ */
public float getTraveledDistance() { public float getTraveledDistance() {
return traveledDistance; return traveledDistance;
} }
} }

@ -1,229 +1,230 @@
/* /*
* Copyright (c) 2009-2012 jMonkeyEngine * Copyright (c) 2009-2012 jMonkeyEngine
* All rights reserved. * All rights reserved.
* *
* Redistribution and use in source and binary forms, with or without * Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are * modification, are permitted provided that the following conditions are
* met: * met:
* *
* * Redistributions of source code must retain the above copyright * * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer. * notice, this list of conditions and the following disclaimer.
* *
* * Redistributions in binary form must reproduce the above copyright * * Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the * notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution. * documentation and/or other materials provided with the distribution.
* *
* * Neither the name of 'jMonkeyEngine' nor the names of its contributors * * Neither the name of 'jMonkeyEngine' nor the names of its contributors
* may be used to endorse or promote products derived from this software * may be used to endorse or promote products derived from this software
* without specific prior written permission. * without specific prior written permission.
* *
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
* TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
* PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/ */
package com.jme3.cinematic.events; package com.jme3.cinematic.events;
import com.jme3.animation.LoopMode; import com.jme3.animation.LoopMode;
import com.jme3.app.Application; import com.jme3.app.Application;
import com.jme3.audio.AudioNode; import com.jme3.audio.AudioNode;
import com.jme3.audio.AudioSource; import com.jme3.audio.AudioSource;
import com.jme3.cinematic.Cinematic; import com.jme3.cinematic.Cinematic;
import com.jme3.export.InputCapsule; import com.jme3.export.InputCapsule;
import com.jme3.export.JmeExporter; 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 java.io.IOException; import java.io.IOException;
/** /**
* A sound track to be played in a cinematic. * A sound track to be played in a cinematic.
* @author Nehon * @author Nehon
*/ */
public class SoundEvent extends AbstractCinematicEvent { public class SoundEvent extends AbstractCinematicEvent {
protected String path; protected String path;
protected AudioNode audioNode; protected AudioNode audioNode;
protected boolean stream = false; protected boolean stream = false;
/** /**
* creates a sound track from the given resource path * creates a sound track from the given resource path
* @param path the path to an audio file (ie : "Sounds/mySound.wav") * @param path the path to an audio file (ie : "Sounds/mySound.wav")
*/ */
public SoundEvent(String path) { public SoundEvent(String path) {
this.path = path; this.path = path;
} }
/** /**
* creates a sound track from the given resource path * creates a sound track from the given resource path
* @param path the path to an audio file (ie : "Sounds/mySound.wav") * @param path the path to an audio file (ie : "Sounds/mySound.wav")
* @param stream true to make the audio data streamed * @param stream true to make the audio data streamed
*/ */
public SoundEvent(String path, boolean stream) { public SoundEvent(String path, boolean stream) {
this(path); this(path);
this.stream = stream; this.stream = stream;
} }
/** /**
* creates a sound track from the given resource path * creates a sound track from the given resource path
* @param path the path to an audio file (ie : "Sounds/mySound.wav") * @param path the path to an audio file (ie : "Sounds/mySound.wav")
* @param stream true to make the audio data streamed * @param stream true to make the audio data streamed
* @param initialDuration the initial duration of the event * @param initialDuration the initial duration of the event
*/ */
public SoundEvent(String path, boolean stream, float initialDuration) { public SoundEvent(String path, boolean stream, float initialDuration) {
super(initialDuration); super(initialDuration);
this.path = path; this.path = path;
this.stream = stream; this.stream = stream;
} }
/** /**
* creates a sound track from the given resource path * creates a sound track from the given resource path
* @param path the path to an audio file (ie : "Sounds/mySound.wav") * @param path the path to an audio file (ie : "Sounds/mySound.wav")
* @param stream true to make the audio data streamed * @param stream true to make the audio data streamed
* @param loopMode the loopMode * @param loopMode the loopMode
* @see LoopMode * @see LoopMode
*/ */
public SoundEvent(String path, boolean stream, LoopMode loopMode) { public SoundEvent(String path, boolean stream, LoopMode loopMode) {
super(loopMode); super(loopMode);
this.path = path; this.path = path;
this.stream = stream; this.stream = stream;
} }
/** /**
* creates a sound track from the given resource path * creates a sound track from the given resource path
* @param path the path to an audio file (ie : "Sounds/mySound.wav") * @param path the path to an audio file (ie : "Sounds/mySound.wav")
* @param stream true to make the audio data streamed * @param stream true to make the audio data streamed
* @param initialDuration the initial duration of the event * @param initialDuration the initial duration of the event
* @param loopMode the loopMode * @param loopMode the loopMode
* @see LoopMode * @see LoopMode
*/ */
public SoundEvent(String path, boolean stream, float initialDuration, LoopMode loopMode) { public SoundEvent(String path, boolean stream, float initialDuration, LoopMode loopMode) {
super(initialDuration, loopMode); super(initialDuration, loopMode);
this.path = path; this.path = path;
this.stream = stream; this.stream = stream;
} }
/** /**
* creates a sound track from the given resource path * creates a sound track from the given resource path
* @param path the path to an audio file (ie : "Sounds/mySound.wav") * @param path the path to an audio file (ie : "Sounds/mySound.wav")
* @param initialDuration the initial duration of the event * @param initialDuration the initial duration of the event
*/ */
public SoundEvent(String path, float initialDuration) { public SoundEvent(String path, float initialDuration) {
super(initialDuration); super(initialDuration);
this.path = path; this.path = path;
} }
/** /**
* creates a sound track from the given resource path * creates a sound track from the given resource path
* @param path the path to an audio file (ie : "Sounds/mySound.wav") * @param path the path to an audio file (ie : "Sounds/mySound.wav")
* @param loopMode the loopMode * @param loopMode the loopMode
* @see LoopMode * @see LoopMode
*/ */
public SoundEvent(String path, LoopMode loopMode) { public SoundEvent(String path, LoopMode loopMode) {
super(loopMode); super(loopMode);
this.path = path; this.path = path;
} }
/** /**
* creates a sound track from the given resource path * creates a sound track from the given resource path
* @param path the path to an audio file (ie : "Sounds/mySound.wav") * @param path the path to an audio file (ie : "Sounds/mySound.wav")
* @param initialDuration the initial duration of the event * @param initialDuration the initial duration of the event
* @param loopMode the loopMode * @param loopMode the loopMode
* @see LoopMode * @see LoopMode
*/ */
public SoundEvent(String path, float initialDuration, LoopMode loopMode) { public SoundEvent(String path, float initialDuration, LoopMode loopMode) {
super(initialDuration, loopMode); super(initialDuration, loopMode);
this.path = path; this.path = path;
} }
/** /**
* creates a sound event * creates a sound event
* used for serialization * used for serialization
*/ */
public SoundEvent() { public SoundEvent() {
} super();
}
@Override
public void initEvent(Application app, Cinematic cinematic) { @Override
super.initEvent(app, cinematic); public void initEvent(Application app, Cinematic cinematic) {
audioNode = new AudioNode(app.getAssetManager(), path, stream); super.initEvent(app, cinematic);
audioNode.setPositional(false); audioNode = new AudioNode(app.getAssetManager(), path, stream);
setLoopMode(loopMode); audioNode.setPositional(false);
} setLoopMode(loopMode);
}
@Override
public void setTime(float time) { @Override
super.setTime(time); public void setTime(float time) {
//can occur on rewind super.setTime(time);
if (time < 0f) { //can occur on rewind
stop(); if (time < 0f) {
}else{ stop();
audioNode.setTimeOffset(time); }else{
} audioNode.setTimeOffset(time);
} }
}
@Override
public void onPlay() { @Override
audioNode.play(); public void onPlay() {
} audioNode.play();
}
@Override
public void onStop() { @Override
audioNode.stop(); public void onStop() {
audioNode.stop();
}
}
@Override
public void onPause() { @Override
audioNode.pause(); public void onPause() {
} audioNode.pause();
}
@Override
public void onUpdate(float tpf) { @Override
if (audioNode.getStatus() == AudioSource.Status.Stopped) { public void onUpdate(float tpf) {
stop(); if (audioNode.getStatus() == AudioSource.Status.Stopped) {
} stop();
} }
}
/**
* Returns the underlying audio node of this sound track /**
* @return * Returns the underlying audio node of this sound track
*/ * @return
public AudioNode getAudioNode() { */
return audioNode; public AudioNode getAudioNode() {
} return audioNode;
}
@Override
public void setLoopMode(LoopMode loopMode) { @Override
super.setLoopMode(loopMode); public void setLoopMode(LoopMode loopMode) {
super.setLoopMode(loopMode);
if (loopMode != LoopMode.DontLoop) {
audioNode.setLooping(true); if (loopMode != LoopMode.DontLoop) {
} else { audioNode.setLooping(true);
audioNode.setLooping(false); } else {
} audioNode.setLooping(false);
} }
}
@Override
public void write(JmeExporter ex) throws IOException { @Override
super.write(ex); public void write(JmeExporter ex) throws IOException {
OutputCapsule oc = ex.getCapsule(this); super.write(ex);
oc.write(path, "path", ""); OutputCapsule oc = ex.getCapsule(this);
oc.write(stream, "stream", false); oc.write(path, "path", "");
} oc.write(stream, "stream", false);
}
@Override
public void read(JmeImporter im) throws IOException { @Override
super.read(im); public void read(JmeImporter im) throws IOException {
InputCapsule ic = im.getCapsule(this); super.read(im);
path = ic.readString("path", ""); InputCapsule ic = im.getCapsule(this);
stream = ic.readBoolean("stream", false); path = ic.readString("path", "");
stream = ic.readBoolean("stream", false);
}
} }
}

@ -1,122 +1,123 @@
/* /*
* Copyright (c) 2009-2012 jMonkeyEngine * Copyright (c) 2009-2012 jMonkeyEngine
* All rights reserved. * All rights reserved.
* *
* Redistribution and use in source and binary forms, with or without * Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are * modification, are permitted provided that the following conditions are
* met: * met:
* *
* * Redistributions of source code must retain the above copyright * * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer. * notice, this list of conditions and the following disclaimer.
* *
* * Redistributions in binary form must reproduce the above copyright * * Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the * notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution. * documentation and/or other materials provided with the distribution.
* *
* * Neither the name of 'jMonkeyEngine' nor the names of its contributors * * Neither the name of 'jMonkeyEngine' nor the names of its contributors
* may be used to endorse or promote products derived from this software * may be used to endorse or promote products derived from this software
* without specific prior written permission. * without specific prior written permission.
* *
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
* TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
* PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/ */
package com.jme3.scene; package com.jme3.scene;
import com.jme3.export.JmeExporter; import com.jme3.export.JmeExporter;
import com.jme3.export.JmeImporter; import com.jme3.export.JmeImporter;
import com.jme3.renderer.Camera; import com.jme3.renderer.Camera;
import com.jme3.scene.control.CameraControl; import com.jme3.scene.control.CameraControl;
import com.jme3.scene.control.CameraControl.ControlDirection; import com.jme3.scene.control.CameraControl.ControlDirection;
import com.jme3.util.clone.Cloner; import com.jme3.util.clone.Cloner;
import java.io.IOException; import java.io.IOException;
/** /**
* <code>CameraNode</code> simply uses {@link CameraControl} to implement * <code>CameraNode</code> simply uses {@link CameraControl} to implement
* linking of camera and node data. * linking of camera and node data.
* *
* @author Tim8Dev * @author Tim8Dev
*/ */
public class CameraNode extends Node { public class CameraNode extends Node {
private CameraControl camControl; private CameraControl camControl;
/** /**
* Serialization only. Do not use. * Serialization only. Do not use.
*/ */
public CameraNode() { public CameraNode() {
} super();
}
public CameraNode(String name, Camera camera) {
this(name, new CameraControl(camera)); public CameraNode(String name, Camera camera) {
} this(name, new CameraControl(camera));
}
public CameraNode(String name, CameraControl control) {
super(name); public CameraNode(String name, CameraControl control) {
addControl(control); super(name);
camControl = control; addControl(control);
} camControl = control;
}
public void setEnabled(boolean enabled) {
camControl.setEnabled(enabled); public void setEnabled(boolean enabled) {
} camControl.setEnabled(enabled);
}
public boolean isEnabled() {
return camControl.isEnabled(); public boolean isEnabled() {
} return camControl.isEnabled();
}
public void setControlDir(ControlDirection controlDir) {
camControl.setControlDir(controlDir); public void setControlDir(ControlDirection controlDir) {
} camControl.setControlDir(controlDir);
}
public void setCamera(Camera camera) {
camControl.setCamera(camera); public void setCamera(Camera camera) {
} camControl.setCamera(camera);
}
public ControlDirection getControlDir() {
return camControl.getControlDir(); public ControlDirection getControlDir() {
} return camControl.getControlDir();
}
public Camera getCamera() {
return camControl.getCamera(); public Camera getCamera() {
} return camControl.getCamera();
}
// @Override
// public void lookAt(Vector3f position, Vector3f upVector) { // @Override
// this.lookAt(position, upVector); // public void lookAt(Vector3f position, Vector3f upVector) {
// camControl.getCamera().lookAt(position, upVector); // this.lookAt(position, upVector);
// } // camControl.getCamera().lookAt(position, upVector);
// }
/**
* Called internally by com.jme3.util.clone.Cloner. Do not call directly. /**
*/ * Called internally by com.jme3.util.clone.Cloner. Do not call directly.
@Override */
public void cloneFields( Cloner cloner, Object original ) { @Override
super.cloneFields(cloner, original); public void cloneFields( Cloner cloner, Object original ) {
super.cloneFields(cloner, original);
// A change in behavior... I think previously CameraNode was probably
// not really cloneable... or at least its camControl would be pointing // A change in behavior... I think previously CameraNode was probably
// to the wrong control. -pspeed // not really cloneable... or at least its camControl would be pointing
this.camControl = cloner.clone(camControl); // to the wrong control. -pspeed
} this.camControl = cloner.clone(camControl);
}
@Override
public void read(JmeImporter im) throws IOException { @Override
super.read(im); public void read(JmeImporter im) throws IOException {
camControl = (CameraControl)im.getCapsule(this).readSavable("camControl", null); super.read(im);
} camControl = (CameraControl)im.getCapsule(this).readSavable("camControl", null);
}
@Override
public void write(JmeExporter ex) throws IOException { @Override
super.write(ex); public void write(JmeExporter ex) throws IOException {
ex.getCapsule(this).write(camControl, "camControl", null); super.write(ex);
} ex.getCapsule(this).write(camControl, "camControl", null);
} }
}

Loading…
Cancel
Save