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
parent
2120c9d334
commit
ae97614c83
@ -1,365 +1,369 @@ |
||||
/* |
||||
* Copyright (c) 2009-2012 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.animation; |
||||
|
||||
import com.jme3.math.FastMath; |
||||
import com.jme3.util.TempVars; |
||||
import java.util.BitSet; |
||||
|
||||
/** |
||||
* <code>AnimChannel</code> provides controls, such as play, pause, |
||||
* fast forward, etc, for an animation. The animation |
||||
* channel may influence the entire model or specific bones of the model's |
||||
* skeleton. A single model may have multiple animation channels influencing |
||||
* various parts of its body. For example, a character model may have an |
||||
* animation channel for its feet, and another for its torso, and |
||||
* the animations for each channel are controlled independently. |
||||
* |
||||
* @author Kirill Vainer |
||||
*/ |
||||
public final class AnimChannel { |
||||
|
||||
private static final float DEFAULT_BLEND_TIME = 0.15f; |
||||
|
||||
private AnimControl control; |
||||
|
||||
private BitSet affectedBones; |
||||
|
||||
private Animation animation; |
||||
private Animation blendFrom; |
||||
private float time; |
||||
private float speed; |
||||
private float timeBlendFrom; |
||||
private float blendTime; |
||||
private float speedBlendFrom; |
||||
private boolean notified=false; |
||||
|
||||
private LoopMode loopMode, loopModeBlendFrom; |
||||
|
||||
private float blendAmount = 1f; |
||||
private float blendRate = 0; |
||||
|
||||
AnimChannel(AnimControl control){ |
||||
this.control = control; |
||||
} |
||||
|
||||
/** |
||||
* Returns the parent control of this AnimChannel. |
||||
* |
||||
* @return the parent control of this AnimChannel. |
||||
* @see AnimControl |
||||
*/ |
||||
public AnimControl getControl() { |
||||
return control; |
||||
} |
||||
|
||||
/** |
||||
* @return The name of the currently playing animation, or null if |
||||
* none is assigned. |
||||
* |
||||
* @see AnimChannel#setAnim(java.lang.String) |
||||
*/ |
||||
public String getAnimationName() { |
||||
return animation != null ? animation.getName() : null; |
||||
} |
||||
|
||||
/** |
||||
* @return The loop mode currently set for the animation. The loop mode |
||||
* determines what will happen to the animation once it finishes |
||||
* playing. |
||||
* |
||||
* For more information, see the LoopMode enum class. |
||||
* @see LoopMode |
||||
* @see AnimChannel#setLoopMode(com.jme3.animation.LoopMode) |
||||
*/ |
||||
public LoopMode getLoopMode() { |
||||
return loopMode; |
||||
} |
||||
|
||||
/** |
||||
* @param loopMode Set the loop mode for the channel. The loop mode |
||||
* determines what will happen to the animation once it finishes |
||||
* playing. |
||||
* |
||||
* For more information, see the LoopMode enum class. |
||||
* @see LoopMode |
||||
*/ |
||||
public void setLoopMode(LoopMode loopMode) { |
||||
this.loopMode = loopMode; |
||||
} |
||||
|
||||
/** |
||||
* @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 |
||||
* at its default speed. |
||||
* |
||||
* @see AnimChannel#setSpeed(float) |
||||
*/ |
||||
public float getSpeed() { |
||||
return speed; |
||||
} |
||||
|
||||
/** |
||||
* @param speed Set the speed of the animation channel. The 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) { |
||||
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) |
||||
*/ |
||||
public float getTime() { |
||||
return time; |
||||
} |
||||
|
||||
/** |
||||
* @param time Set the time of the currently playing animation, the time |
||||
* is clamped from 0 to {@link #getAnimMaxTime()}. |
||||
*/ |
||||
public void setTime(float time) { |
||||
this.time = FastMath.clamp(time, 0, getAnimMaxTime()); |
||||
} |
||||
|
||||
/** |
||||
* @return The length of the currently playing animation, or zero |
||||
* if no animation is playing. |
||||
* |
||||
* @see AnimChannel#getTime() |
||||
*/ |
||||
public float getAnimMaxTime(){ |
||||
return animation != null ? animation.getLength() : 0f; |
||||
} |
||||
|
||||
/** |
||||
* Set the current animation that is played by this AnimChannel. |
||||
* <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. |
||||
* |
||||
* @param name The name of the animation to play |
||||
* @param blendTime The blend time over which to blend the new animation |
||||
* with the old one. If zero, then no blending will occur and the new |
||||
* animation will be applied instantly. |
||||
*/ |
||||
public void setAnim(String name, float blendTime){ |
||||
if (name == null) |
||||
throw new IllegalArgumentException("name cannot be null"); |
||||
|
||||
if (blendTime < 0f) |
||||
throw new IllegalArgumentException("blendTime cannot be less than zero"); |
||||
|
||||
Animation anim = control.animationMap.get(name); |
||||
if (anim == null) |
||||
throw new IllegalArgumentException("Cannot find animation named: '"+name+"'"); |
||||
|
||||
control.notifyAnimChange(this, name); |
||||
|
||||
if (animation != null && blendTime > 0f){ |
||||
this.blendTime = blendTime; |
||||
// activate blending
|
||||
blendTime = Math.min(blendTime, anim.getLength() / speed); |
||||
blendFrom = animation; |
||||
timeBlendFrom = time; |
||||
speedBlendFrom = speed; |
||||
loopModeBlendFrom = loopMode; |
||||
blendAmount = 0f; |
||||
blendRate = 1f / blendTime; |
||||
}else{ |
||||
blendFrom = null; |
||||
} |
||||
|
||||
animation = anim; |
||||
time = 0; |
||||
speed = 1f; |
||||
loopMode = LoopMode.Loop; |
||||
notified = false; |
||||
} |
||||
|
||||
/** |
||||
* Set the current animation that is played by this AnimChannel. |
||||
* <p> |
||||
* See {@link #setAnim(java.lang.String, float)}. |
||||
* The blendTime argument by default is 150 milliseconds. |
||||
* |
||||
* @param name The name of the animation to play |
||||
*/ |
||||
public void setAnim(String name){ |
||||
setAnim(name, DEFAULT_BLEND_TIME); |
||||
} |
||||
|
||||
/** |
||||
* Add all the bones of the model's skeleton to be |
||||
* influenced by this animation channel. |
||||
*/ |
||||
public void addAllBones() { |
||||
affectedBones = null; |
||||
} |
||||
|
||||
/** |
||||
* Add a single bone to be influenced by this animation channel. |
||||
*/ |
||||
public void addBone(String name) { |
||||
addBone(control.getSkeleton().getBone(name)); |
||||
} |
||||
|
||||
/** |
||||
* Add a single bone to be influenced by this animation channel. |
||||
*/ |
||||
public void addBone(Bone bone) { |
||||
int boneIndex = control.getSkeleton().getBoneIndex(bone); |
||||
if(affectedBones == null) { |
||||
affectedBones = new BitSet(control.getSkeleton().getBoneCount()); |
||||
} |
||||
affectedBones.set(boneIndex); |
||||
} |
||||
|
||||
/** |
||||
* 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) { |
||||
addToRootBone(control.getSkeleton().getBone(name)); |
||||
} |
||||
|
||||
/** |
||||
* Add bones to be influenced by this animation channel starting from the |
||||
* given bone and going toward the root 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 bone and going toward its children. |
||||
*/ |
||||
public void addFromRootBone(Bone bone) { |
||||
addBone(bone); |
||||
if (bone.getChildren() == null) |
||||
return; |
||||
for (Bone childBone : bone.getChildren()) { |
||||
addBone(childBone); |
||||
addFromRootBone(childBone); |
||||
} |
||||
} |
||||
|
||||
BitSet getAffectedBones(){ |
||||
return affectedBones; |
||||
} |
||||
|
||||
public void reset(boolean rewind){ |
||||
if(rewind){ |
||||
setTime(0); |
||||
if(control.getSkeleton()!=null){ |
||||
control.getSkeleton().resetAndUpdate(); |
||||
}else{ |
||||
TempVars vars = TempVars.get(); |
||||
update(0, vars); |
||||
vars.release(); |
||||
} |
||||
} |
||||
animation = null; |
||||
notified = false; |
||||
} |
||||
|
||||
void update(float tpf, TempVars vars) { |
||||
if (animation == null) |
||||
return; |
||||
|
||||
if (blendFrom != null && blendAmount != 1.0f){ |
||||
// The blendFrom anim is set, the actual animation
|
||||
// playing will be set
|
||||
// blendFrom.setTime(timeBlendFrom, 1f, control, this, vars);
|
||||
blendFrom.setTime(timeBlendFrom, 1f - blendAmount, control, this, vars); |
||||
|
||||
timeBlendFrom += tpf * speedBlendFrom; |
||||
timeBlendFrom = AnimationUtils.clampWrapTime(timeBlendFrom, |
||||
blendFrom.getLength(), |
||||
loopModeBlendFrom); |
||||
if (timeBlendFrom < 0){ |
||||
timeBlendFrom = -timeBlendFrom; |
||||
speedBlendFrom = -speedBlendFrom; |
||||
} |
||||
|
||||
blendAmount += tpf * blendRate; |
||||
if (blendAmount > 1f){ |
||||
blendAmount = 1f; |
||||
blendFrom = null; |
||||
} |
||||
} |
||||
|
||||
animation.setTime(time, blendAmount, control, this, vars); |
||||
time += tpf * speed; |
||||
if (animation.getLength() > 0){ |
||||
if (!notified && (time >= animation.getLength() || time < 0)) { |
||||
if (loopMode == LoopMode.DontLoop) { |
||||
// Note that this flag has to be set before calling the notify
|
||||
// since the notify may start a new animation and then unset
|
||||
// the flag.
|
||||
notified = true; |
||||
} |
||||
control.notifyAnimCycleDone(this, animation.getName()); |
||||
} |
||||
} |
||||
time = AnimationUtils.clampWrapTime(time, animation.getLength(), loopMode); |
||||
if (time < 0){ |
||||
// Negative time indicates that speed should be inverted
|
||||
// (for cycle loop mode only)
|
||||
time = -time; |
||||
speed = -speed; |
||||
} |
||||
} |
||||
} |
||||
/* |
||||
* Copyright (c) 2009-2012 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.animation; |
||||
|
||||
import com.jme3.math.FastMath; |
||||
import com.jme3.util.TempVars; |
||||
import java.util.BitSet; |
||||
|
||||
/** |
||||
* <code>AnimChannel</code> provides controls, such as play, pause, |
||||
* fast forward, etc, for an animation. The animation |
||||
* channel may influence the entire model or specific bones of the model's |
||||
* skeleton. A single model may have multiple animation channels influencing |
||||
* various parts of its body. For example, a character model may have an |
||||
* animation channel for its feet, and another for its torso, and |
||||
* the animations for each channel are controlled independently. |
||||
* |
||||
* @author Kirill Vainer |
||||
*/ |
||||
public final class AnimChannel { |
||||
|
||||
private static final float DEFAULT_BLEND_TIME = 0.15f; |
||||
|
||||
private AnimControl control; |
||||
|
||||
private BitSet affectedBones; |
||||
|
||||
private Animation animation; |
||||
private Animation blendFrom; |
||||
private float time; |
||||
private float speed; |
||||
private float timeBlendFrom; |
||||
private float blendTime; |
||||
private float speedBlendFrom; |
||||
private boolean notified=false; |
||||
|
||||
private LoopMode loopMode, loopModeBlendFrom; |
||||
|
||||
private float blendAmount = 1f; |
||||
private float blendRate = 0; |
||||
|
||||
public AnimChannel(){ |
||||
|
||||
} |
||||
|
||||
public AnimChannel(AnimControl control){ |
||||
this.control = control; |
||||
} |
||||
|
||||
/** |
||||
* Returns the parent control of this AnimChannel. |
||||
* |
||||
* @return the parent control of this AnimChannel. |
||||
* @see AnimControl |
||||
*/ |
||||
public AnimControl getControl() { |
||||
return control; |
||||
} |
||||
|
||||
/** |
||||
* @return The name of the currently playing animation, or null if |
||||
* none is assigned. |
||||
* |
||||
* @see AnimChannel#setAnim(java.lang.String) |
||||
*/ |
||||
public String getAnimationName() { |
||||
return animation != null ? animation.getName() : null; |
||||
} |
||||
|
||||
/** |
||||
* @return The loop mode currently set for the animation. The loop mode |
||||
* determines what will happen to the animation once it finishes |
||||
* playing. |
||||
* |
||||
* For more information, see the LoopMode enum class. |
||||
* @see LoopMode |
||||
* @see AnimChannel#setLoopMode(com.jme3.animation.LoopMode) |
||||
*/ |
||||
public LoopMode getLoopMode() { |
||||
return loopMode; |
||||
} |
||||
|
||||
/** |
||||
* @param loopMode Set the loop mode for the channel. The loop mode |
||||
* determines what will happen to the animation once it finishes |
||||
* playing. |
||||
* |
||||
* For more information, see the LoopMode enum class. |
||||
* @see LoopMode |
||||
*/ |
||||
public void setLoopMode(LoopMode loopMode) { |
||||
this.loopMode = loopMode; |
||||
} |
||||
|
||||
/** |
||||
* @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 |
||||
* at its default speed. |
||||
* |
||||
* @see AnimChannel#setSpeed(float) |
||||
*/ |
||||
public float getSpeed() { |
||||
return speed; |
||||
} |
||||
|
||||
/** |
||||
* @param speed Set the speed of the animation channel. The 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) { |
||||
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) |
||||
*/ |
||||
public float getTime() { |
||||
return time; |
||||
} |
||||
|
||||
/** |
||||
* @param time Set the time of the currently playing animation, the time |
||||
* is clamped from 0 to {@link #getAnimMaxTime()}. |
||||
*/ |
||||
public void setTime(float time) { |
||||
this.time = FastMath.clamp(time, 0, getAnimMaxTime()); |
||||
} |
||||
|
||||
/** |
||||
* @return The length of the currently playing animation, or zero |
||||
* if no animation is playing. |
||||
* |
||||
* @see AnimChannel#getTime() |
||||
*/ |
||||
public float getAnimMaxTime(){ |
||||
return animation != null ? animation.getLength() : 0f; |
||||
} |
||||
|
||||
/** |
||||
* Set the current animation that is played by this AnimChannel. |
||||
* <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. |
||||
* |
||||
* @param name The name of the animation to play |
||||
* @param blendTime The blend time over which to blend the new animation |
||||
* with the old one. If zero, then no blending will occur and the new |
||||
* animation will be applied instantly. |
||||
*/ |
||||
public void setAnim(String name, float blendTime){ |
||||
if (name == null) |
||||
throw new IllegalArgumentException("name cannot be null"); |
||||
|
||||
if (blendTime < 0f) |
||||
throw new IllegalArgumentException("blendTime cannot be less than zero"); |
||||
|
||||
Animation anim = control.animationMap.get(name); |
||||
if (anim == null) |
||||
throw new IllegalArgumentException("Cannot find animation named: '"+name+"'"); |
||||
|
||||
control.notifyAnimChange(this, name); |
||||
|
||||
if (animation != null && blendTime > 0f){ |
||||
this.blendTime = blendTime; |
||||
// activate blending
|
||||
blendTime = Math.min(blendTime, anim.getLength() / speed); |
||||
blendFrom = animation; |
||||
timeBlendFrom = time; |
||||
speedBlendFrom = speed; |
||||
loopModeBlendFrom = loopMode; |
||||
blendAmount = 0f; |
||||
blendRate = 1f / blendTime; |
||||
}else{ |
||||
blendFrom = null; |
||||
} |
||||
|
||||
animation = anim; |
||||
time = 0; |
||||
speed = 1f; |
||||
loopMode = LoopMode.Loop; |
||||
notified = false; |
||||
} |
||||
|
||||
/** |
||||
* Set the current animation that is played by this AnimChannel. |
||||
* <p> |
||||
* See {@link #setAnim(java.lang.String, float)}. |
||||
* The blendTime argument by default is 150 milliseconds. |
||||
* |
||||
* @param name The name of the animation to play |
||||
*/ |
||||
public void setAnim(String name){ |
||||
setAnim(name, DEFAULT_BLEND_TIME); |
||||
} |
||||
|
||||
/** |
||||
* Add all the bones of the model's skeleton to be |
||||
* influenced by this animation channel. |
||||
*/ |
||||
public void addAllBones() { |
||||
affectedBones = null; |
||||
} |
||||
|
||||
/** |
||||
* Add a single bone to be influenced by this animation channel. |
||||
*/ |
||||
public void addBone(String name) { |
||||
addBone(control.getSkeleton().getBone(name)); |
||||
} |
||||
|
||||
/** |
||||
* Add a single bone to be influenced by this animation channel. |
||||
*/ |
||||
public void addBone(Bone bone) { |
||||
int boneIndex = control.getSkeleton().getBoneIndex(bone); |
||||
if(affectedBones == null) { |
||||
affectedBones = new BitSet(control.getSkeleton().getBoneCount()); |
||||
} |
||||
affectedBones.set(boneIndex); |
||||
} |
||||
|
||||
/** |
||||
* 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) { |
||||
addToRootBone(control.getSkeleton().getBone(name)); |
||||
} |
||||
|
||||
/** |
||||
* Add bones to be influenced by this animation channel starting from the |
||||
* given bone and going toward the root 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 bone and going toward its children. |
||||
*/ |
||||
public void addFromRootBone(Bone bone) { |
||||
addBone(bone); |
||||
if (bone.getChildren() == null) |
||||
return; |
||||
for (Bone childBone : bone.getChildren()) { |
||||
addBone(childBone); |
||||
addFromRootBone(childBone); |
||||
} |
||||
} |
||||
|
||||
BitSet getAffectedBones(){ |
||||
return affectedBones; |
||||
} |
||||
|
||||
public void reset(boolean rewind){ |
||||
if(rewind){ |
||||
setTime(0); |
||||
if(control.getSkeleton()!=null){ |
||||
control.getSkeleton().resetAndUpdate(); |
||||
}else{ |
||||
TempVars vars = TempVars.get(); |
||||
update(0, vars); |
||||
vars.release(); |
||||
} |
||||
} |
||||
animation = null; |
||||
notified = false; |
||||
} |
||||
|
||||
void update(float tpf, TempVars vars) { |
||||
if (animation == null) |
||||
return; |
||||
|
||||
if (blendFrom != null && blendAmount != 1.0f){ |
||||
// The blendFrom anim is set, the actual animation
|
||||
// playing will be set
|
||||
// blendFrom.setTime(timeBlendFrom, 1f, control, this, vars);
|
||||
blendFrom.setTime(timeBlendFrom, 1f - blendAmount, control, this, vars); |
||||
|
||||
timeBlendFrom += tpf * speedBlendFrom; |
||||
timeBlendFrom = AnimationUtils.clampWrapTime(timeBlendFrom, |
||||
blendFrom.getLength(), |
||||
loopModeBlendFrom); |
||||
if (timeBlendFrom < 0){ |
||||
timeBlendFrom = -timeBlendFrom; |
||||
speedBlendFrom = -speedBlendFrom; |
||||
} |
||||
|
||||
blendAmount += tpf * blendRate; |
||||
if (blendAmount > 1f){ |
||||
blendAmount = 1f; |
||||
blendFrom = null; |
||||
} |
||||
} |
||||
|
||||
animation.setTime(time, blendAmount, control, this, vars); |
||||
time += tpf * speed; |
||||
if (animation.getLength() > 0){ |
||||
if (!notified && (time >= animation.getLength() || time < 0)) { |
||||
if (loopMode == LoopMode.DontLoop) { |
||||
// Note that this flag has to be set before calling the notify
|
||||
// since the notify may start a new animation and then unset
|
||||
// the flag.
|
||||
notified = true; |
||||
} |
||||
control.notifyAnimCycleDone(this, animation.getName()); |
||||
} |
||||
} |
||||
time = AnimationUtils.clampWrapTime(time, animation.getLength(), loopMode); |
||||
if (time < 0){ |
||||
// Negative time indicates that speed should be inverted
|
||||
// (for cycle loop mode only)
|
||||
time = -time; |
||||
speed = -speed; |
||||
} |
||||
} |
||||
} |
||||
|
File diff suppressed because it is too large
Load Diff
@ -1,89 +1,93 @@ |
||||
/* |
||||
* Copyright (c) 2009-2012 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; |
||||
|
||||
import com.jme3.cinematic.events.CinematicEvent; |
||||
import com.jme3.export.*; |
||||
import java.io.IOException; |
||||
import java.util.ArrayList; |
||||
import java.util.List; |
||||
|
||||
/** |
||||
* |
||||
* @author Nehon |
||||
*/ |
||||
public class KeyFrame implements Savable { |
||||
|
||||
List<CinematicEvent> cinematicEvents = new ArrayList<CinematicEvent>(); |
||||
private int index; |
||||
|
||||
public List<CinematicEvent> getCinematicEvents() { |
||||
return cinematicEvents; |
||||
} |
||||
|
||||
public void setCinematicEvents(List<CinematicEvent> cinematicEvents) { |
||||
this.cinematicEvents = cinematicEvents; |
||||
} |
||||
|
||||
public List<CinematicEvent> trigger() { |
||||
for (CinematicEvent event : cinematicEvents) { |
||||
event.play(); |
||||
} |
||||
return cinematicEvents; |
||||
} |
||||
|
||||
public boolean isEmpty(){ |
||||
return cinematicEvents.isEmpty(); |
||||
} |
||||
|
||||
public void write(JmeExporter ex) throws IOException { |
||||
OutputCapsule oc = ex.getCapsule(this); |
||||
oc.writeSavableArrayList((ArrayList) cinematicEvents, "cinematicEvents", null); |
||||
oc.write(index, "index", 0); |
||||
} |
||||
|
||||
public void read(JmeImporter im) throws IOException { |
||||
InputCapsule ic = im.getCapsule(this); |
||||
cinematicEvents = ic.readSavableArrayList("cinematicEvents", null); |
||||
index=ic.readInt("index", 0); |
||||
} |
||||
|
||||
public int getIndex() { |
||||
return index; |
||||
} |
||||
|
||||
public void setIndex(int index) { |
||||
this.index = index; |
||||
} |
||||
|
||||
|
||||
} |
||||
/* |
||||
* Copyright (c) 2009-2012 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; |
||||
|
||||
import com.jme3.cinematic.events.CinematicEvent; |
||||
import com.jme3.export.*; |
||||
import java.io.IOException; |
||||
import java.util.ArrayList; |
||||
import java.util.List; |
||||
|
||||
/** |
||||
* |
||||
* @author Nehon |
||||
*/ |
||||
public class KeyFrame implements Savable { |
||||
|
||||
public KeyFrame(){ |
||||
|
||||
} |
||||
|
||||
List<CinematicEvent> cinematicEvents = new ArrayList<>(); |
||||
private int index; |
||||
|
||||
public List<CinematicEvent> getCinematicEvents() { |
||||
return cinematicEvents; |
||||
} |
||||
|
||||
public void setCinematicEvents(List<CinematicEvent> cinematicEvents) { |
||||
this.cinematicEvents = cinematicEvents; |
||||
} |
||||
|
||||
public List<CinematicEvent> trigger() { |
||||
for (CinematicEvent event : cinematicEvents) { |
||||
event.play(); |
||||
} |
||||
return cinematicEvents; |
||||
} |
||||
|
||||
public boolean isEmpty(){ |
||||
return cinematicEvents.isEmpty(); |
||||
} |
||||
|
||||
public void write(JmeExporter ex) throws IOException { |
||||
OutputCapsule oc = ex.getCapsule(this); |
||||
oc.writeSavableArrayList((ArrayList) cinematicEvents, "cinematicEvents", null); |
||||
oc.write(index, "index", 0); |
||||
} |
||||
|
||||
public void read(JmeImporter im) throws IOException { |
||||
InputCapsule ic = im.getCapsule(this); |
||||
cinematicEvents = ic.readSavableArrayList("cinematicEvents", null); |
||||
index=ic.readInt("index", 0); |
||||
} |
||||
|
||||
public int getIndex() { |
||||
return index; |
||||
} |
||||
|
||||
public void setIndex(int index) { |
||||
this.index = index; |
||||
} |
||||
|
||||
|
||||
} |
||||
|
@ -1,447 +1,448 @@ |
||||
/* |
||||
* Copyright (c) 2009-2012 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.animation.AnimChannel; |
||||
import com.jme3.animation.AnimControl; |
||||
import com.jme3.animation.LoopMode; |
||||
import com.jme3.app.Application; |
||||
import com.jme3.cinematic.Cinematic; |
||||
import com.jme3.cinematic.PlayState; |
||||
import com.jme3.export.InputCapsule; |
||||
import com.jme3.export.JmeExporter; |
||||
import com.jme3.export.JmeImporter; |
||||
import com.jme3.export.OutputCapsule; |
||||
import com.jme3.scene.Spatial; |
||||
import java.io.IOException; |
||||
import java.util.Collection; |
||||
import java.util.HashMap; |
||||
import java.util.Map; |
||||
import java.util.logging.Logger; |
||||
|
||||
/** |
||||
* An event based on an animation of a model. The model has to hold an |
||||
* AnimControl with valid animation (bone or spatial animations). |
||||
* |
||||
* It helps to schedule the playback of an animation on a model in a Cinematic. |
||||
* |
||||
* |
||||
* @author Nehon |
||||
*/ |
||||
public class AnimationEvent extends AbstractCinematicEvent { |
||||
|
||||
// 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
|
||||
//For backward compatibility, if the model is null it's looked up into the scene
|
||||
public static final int SAVABLE_VERSION = 2; |
||||
private static final Logger log = Logger.getLogger(AnimationEvent.class.getName()); |
||||
public static final String MODEL_CHANNELS = "modelChannels"; |
||||
protected AnimChannel channel; |
||||
protected String animationName; |
||||
protected Spatial model; |
||||
//kept for backward compatibility
|
||||
protected String modelName; |
||||
protected float blendTime = 0; |
||||
protected int channelIndex = 0; |
||||
// parent cinematic
|
||||
protected Cinematic cinematic; |
||||
|
||||
/** |
||||
* used for serialization don't call directly use one of the following |
||||
* constructors |
||||
*/ |
||||
public AnimationEvent() { |
||||
} |
||||
|
||||
/** |
||||
* creates an animation event |
||||
* |
||||
* @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; |
||||
this.animationName = animationName; |
||||
initialDuration = model.getControl(AnimControl.class).getAnimationLength(animationName); |
||||
} |
||||
|
||||
/** |
||||
* 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 initialDuration the initial duration of the event |
||||
*/ |
||||
public AnimationEvent(Spatial model, String animationName, float initialDuration) { |
||||
super(initialDuration); |
||||
this.model = model; |
||||
this.animationName = animationName; |
||||
} |
||||
|
||||
/** |
||||
* 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 loopMode the loopMode |
||||
* @see LoopMode |
||||
*/ |
||||
public AnimationEvent(Spatial model, String animationName, LoopMode loopMode) { |
||||
super(loopMode); |
||||
initialDuration = model.getControl(AnimControl.class).getAnimationLength(animationName); |
||||
this.model = model; |
||||
this.animationName = animationName; |
||||
} |
||||
|
||||
/** |
||||
* 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 initialDuration the initial duration of the event |
||||
* @param loopMode the loopMode |
||||
* @see LoopMode |
||||
*/ |
||||
public AnimationEvent(Spatial model, String animationName, float initialDuration, LoopMode loopMode) { |
||||
super(initialDuration, loopMode); |
||||
this.model = model; |
||||
this.animationName = animationName; |
||||
} |
||||
|
||||
/** |
||||
* 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 initialDuration the initial duration of the event |
||||
* @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); |
||||
this.model = model; |
||||
this.animationName = animationName; |
||||
this.blendTime = blendTime; |
||||
} |
||||
|
||||
/** |
||||
* 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 loopMode the loopMode |
||||
* @see LoopMode |
||||
* @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); |
||||
initialDuration = model.getControl(AnimControl.class).getAnimationLength(animationName); |
||||
this.model = model; |
||||
this.animationName = animationName; |
||||
this.blendTime = blendTime; |
||||
} |
||||
|
||||
/** |
||||
* 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 initialDuration the initial duration of the event |
||||
* @param loopMode the loopMode |
||||
* @see LoopMode |
||||
* @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); |
||||
this.model = model; |
||||
this.animationName = animationName; |
||||
this.blendTime = blendTime; |
||||
} |
||||
|
||||
/** |
||||
* 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 loopMode the loopMode |
||||
* @see LoopMode |
||||
* @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); |
||||
initialDuration = model.getControl(AnimControl.class).getAnimationLength(animationName); |
||||
this.model = model; |
||||
this.animationName = animationName; |
||||
this.channelIndex = channelIndex; |
||||
} |
||||
|
||||
/** |
||||
* 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 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; |
||||
this.animationName = animationName; |
||||
initialDuration = model.getControl(AnimControl.class).getAnimationLength(animationName); |
||||
this.channelIndex = channelIndex; |
||||
} |
||||
|
||||
/** |
||||
* 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 channelIndex the index of the channel default is 0. Events on the |
||||
* @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; |
||||
this.animationName = animationName; |
||||
this.loopMode = loopMode; |
||||
initialDuration = model.getControl(AnimControl.class).getAnimationLength(animationName); |
||||
this.channelIndex = channelIndex; |
||||
this.blendTime = blendTime; |
||||
} |
||||
|
||||
/** |
||||
* 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 initialDuration the initial duration of the event |
||||
* @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); |
||||
this.model = model; |
||||
this.animationName = animationName; |
||||
this.channelIndex = channelIndex; |
||||
} |
||||
|
||||
/** |
||||
* 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 initialDuration the initial duration of the event |
||||
* @param loopMode the loopMode |
||||
* @see LoopMode |
||||
* @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); |
||||
this.model = model; |
||||
this.animationName = animationName; |
||||
this.channelIndex = channelIndex; |
||||
} |
||||
|
||||
@Override |
||||
public void initEvent(Application app, Cinematic cinematic) { |
||||
super.initEvent(app, cinematic); |
||||
this.cinematic = cinematic; |
||||
if (channel == null) { |
||||
Object s = cinematic.getEventData(MODEL_CHANNELS, model); |
||||
if (s == null) { |
||||
s = new HashMap<Integer, AnimChannel>(); |
||||
int numChannels = model.getControl(AnimControl.class).getNumChannels(); |
||||
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); |
||||
} |
||||
|
||||
Map<Integer, AnimChannel> map = (Map<Integer, AnimChannel>) s; |
||||
this.channel = map.get(channelIndex); |
||||
if (this.channel == null) { |
||||
if (model == null) { |
||||
//the model is null we try to find it according to the name
|
||||
//this should occur only when loading an old saved cinematic
|
||||
//othewise it's an error
|
||||
model = cinematic.getScene().getChild(modelName); |
||||
} |
||||
if (model != null) { |
||||
channel = model.getControl(AnimControl.class).createChannel(); |
||||
map.put(channelIndex, channel); |
||||
} else { |
||||
//it's an error
|
||||
throw new UnsupportedOperationException("model should not be null"); |
||||
} |
||||
} |
||||
|
||||
} |
||||
} |
||||
|
||||
@Override |
||||
public void setTime(float time) { |
||||
super.setTime(time); |
||||
if (!animationName.equals(channel.getAnimationName())) { |
||||
channel.setAnim(animationName, blendTime); |
||||
} |
||||
float t = time; |
||||
if (loopMode == loopMode.Loop) { |
||||
t = t % channel.getAnimMaxTime(); |
||||
} |
||||
if (loopMode == loopMode.Cycle) { |
||||
float parity = (float) Math.ceil(time / channel.getAnimMaxTime()); |
||||
if (parity > 0 && parity % 2 == 0) { |
||||
t = channel.getAnimMaxTime() - t % channel.getAnimMaxTime(); |
||||
} else { |
||||
t = t % channel.getAnimMaxTime(); |
||||
} |
||||
|
||||
} |
||||
if (t < 0) { |
||||
channel.setTime(0); |
||||
channel.reset(true); |
||||
} |
||||
if (t > channel.getAnimMaxTime()) { |
||||
channel.setTime(t); |
||||
channel.getControl().update(0); |
||||
stop(); |
||||
} else { |
||||
channel.setTime(t); |
||||
channel.getControl().update(0); |
||||
} |
||||
|
||||
} |
||||
|
||||
@Override |
||||
public void onPlay() { |
||||
channel.getControl().setEnabled(true); |
||||
if (playState == PlayState.Stopped) { |
||||
channel.setAnim(animationName, blendTime); |
||||
channel.setSpeed(speed); |
||||
channel.setLoopMode(loopMode); |
||||
channel.setTime(0); |
||||
} |
||||
} |
||||
|
||||
@Override |
||||
public void setSpeed(float speed) { |
||||
super.setSpeed(speed); |
||||
if (channel != null) { |
||||
channel.setSpeed(speed); |
||||
} |
||||
} |
||||
|
||||
@Override |
||||
public void onUpdate(float tpf) { |
||||
} |
||||
|
||||
@Override |
||||
public void onStop() { |
||||
} |
||||
|
||||
@Override |
||||
public void forceStop() { |
||||
if (channel != null) { |
||||
channel.setTime(time); |
||||
channel.reset(false); |
||||
} |
||||
super.forceStop(); |
||||
} |
||||
|
||||
@Override |
||||
public void onPause() { |
||||
if (channel != null) { |
||||
channel.getControl().setEnabled(false); |
||||
} |
||||
} |
||||
|
||||
@Override |
||||
public void setLoopMode(LoopMode loopMode) { |
||||
super.setLoopMode(loopMode); |
||||
if (channel != null) { |
||||
channel.setLoopMode(loopMode); |
||||
} |
||||
} |
||||
|
||||
@Override |
||||
public void write(JmeExporter ex) throws IOException { |
||||
super.write(ex); |
||||
OutputCapsule oc = ex.getCapsule(this); |
||||
|
||||
oc.write(model, "model", null); |
||||
oc.write(animationName, "animationName", ""); |
||||
oc.write(blendTime, "blendTime", 0f); |
||||
oc.write(channelIndex, "channelIndex", 0); |
||||
|
||||
} |
||||
|
||||
@Override |
||||
public void read(JmeImporter im) throws IOException { |
||||
super.read(im); |
||||
InputCapsule ic = im.getCapsule(this); |
||||
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
|
||||
//scene sub scenegraph to find the correct instance of the model
|
||||
//This brings a reflaxion about the cinematic being an appstate,
|
||||
//shouldn't it be a control over the scene
|
||||
// this would allow to use the cloneForSpatial method and automatically
|
||||
//rebind cloned references of original objects.
|
||||
//for now as nobody probably ever saved a cinematic, this is not a critical issue
|
||||
model = (Spatial) ic.readSavable("model", null); |
||||
animationName = ic.readString("animationName", ""); |
||||
blendTime = ic.readFloat("blendTime", 0f); |
||||
channelIndex = ic.readInt("channelIndex", 0); |
||||
} |
||||
|
||||
@Override |
||||
public void dispose() { |
||||
super.dispose(); |
||||
if (cinematic != null) { |
||||
Object o = cinematic.getEventData(MODEL_CHANNELS, model); |
||||
if (o != null) { |
||||
Collection<AnimChannel> values = ((HashMap<Integer, AnimChannel>) o).values(); |
||||
while (values.remove(channel)); |
||||
if (values.isEmpty()) { |
||||
cinematic.removeEventData(MODEL_CHANNELS, model); |
||||
} |
||||
} |
||||
cinematic = null; |
||||
channel = null; |
||||
} |
||||
} |
||||
} |
||||
/* |
||||
* Copyright (c) 2009-2012 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.animation.AnimChannel; |
||||
import com.jme3.animation.AnimControl; |
||||
import com.jme3.animation.LoopMode; |
||||
import com.jme3.app.Application; |
||||
import com.jme3.cinematic.Cinematic; |
||||
import com.jme3.cinematic.PlayState; |
||||
import com.jme3.export.InputCapsule; |
||||
import com.jme3.export.JmeExporter; |
||||
import com.jme3.export.JmeImporter; |
||||
import com.jme3.export.OutputCapsule; |
||||
import com.jme3.scene.Spatial; |
||||
import java.io.IOException; |
||||
import java.util.Collection; |
||||
import java.util.HashMap; |
||||
import java.util.Map; |
||||
import java.util.logging.Logger; |
||||
|
||||
/** |
||||
* An event based on an animation of a model. The model has to hold an |
||||
* AnimControl with valid animation (bone or spatial animations). |
||||
* |
||||
* It helps to schedule the playback of an animation on a model in a Cinematic. |
||||
* |
||||
* |
||||
* @author Nehon |
||||
*/ |
||||
public class AnimationEvent extends AbstractCinematicEvent { |
||||
|
||||
// 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
|
||||
//For backward compatibility, if the model is null it's looked up into the scene
|
||||
public static final int SAVABLE_VERSION = 2; |
||||
private static final Logger log = Logger.getLogger(AnimationEvent.class.getName()); |
||||
public static final String MODEL_CHANNELS = "modelChannels"; |
||||
protected AnimChannel channel; |
||||
protected String animationName; |
||||
protected Spatial model; |
||||
//kept for backward compatibility
|
||||
protected String modelName; |
||||
protected float blendTime = 0; |
||||
protected int channelIndex = 0; |
||||
// parent cinematic
|
||||
protected Cinematic cinematic; |
||||
|
||||
/** |
||||
* used for serialization don't call directly use one of the following |
||||
* constructors |
||||
*/ |
||||
public AnimationEvent() { |
||||
super(); |
||||
} |
||||
|
||||
/** |
||||
* creates an animation event |
||||
* |
||||
* @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; |
||||
this.animationName = animationName; |
||||
initialDuration = model.getControl(AnimControl.class).getAnimationLength(animationName); |
||||
} |
||||
|
||||
/** |
||||
* 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 initialDuration the initial duration of the event |
||||
*/ |
||||
public AnimationEvent(Spatial model, String animationName, float initialDuration) { |
||||
super(initialDuration); |
||||
this.model = model; |
||||
this.animationName = animationName; |
||||
} |
||||
|
||||
/** |
||||
* 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 loopMode the loopMode |
||||
* @see LoopMode |
||||
*/ |
||||
public AnimationEvent(Spatial model, String animationName, LoopMode loopMode) { |
||||
super(loopMode); |
||||
initialDuration = model.getControl(AnimControl.class).getAnimationLength(animationName); |
||||
this.model = model; |
||||
this.animationName = animationName; |
||||
} |
||||
|
||||
/** |
||||
* 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 initialDuration the initial duration of the event |
||||
* @param loopMode the loopMode |
||||
* @see LoopMode |
||||
*/ |
||||
public AnimationEvent(Spatial model, String animationName, float initialDuration, LoopMode loopMode) { |
||||
super(initialDuration, loopMode); |
||||
this.model = model; |
||||
this.animationName = animationName; |
||||
} |
||||
|
||||
/** |
||||
* 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 initialDuration the initial duration of the event |
||||
* @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); |
||||
this.model = model; |
||||
this.animationName = animationName; |
||||
this.blendTime = blendTime; |
||||
} |
||||
|
||||
/** |
||||
* 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 loopMode the loopMode |
||||
* @see LoopMode |
||||
* @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); |
||||
initialDuration = model.getControl(AnimControl.class).getAnimationLength(animationName); |
||||
this.model = model; |
||||
this.animationName = animationName; |
||||
this.blendTime = blendTime; |
||||
} |
||||
|
||||
/** |
||||
* 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 initialDuration the initial duration of the event |
||||
* @param loopMode the loopMode |
||||
* @see LoopMode |
||||
* @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); |
||||
this.model = model; |
||||
this.animationName = animationName; |
||||
this.blendTime = blendTime; |
||||
} |
||||
|
||||
/** |
||||
* 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 loopMode the loopMode |
||||
* @see LoopMode |
||||
* @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); |
||||
initialDuration = model.getControl(AnimControl.class).getAnimationLength(animationName); |
||||
this.model = model; |
||||
this.animationName = animationName; |
||||
this.channelIndex = channelIndex; |
||||
} |
||||
|
||||
/** |
||||
* 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 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; |
||||
this.animationName = animationName; |
||||
initialDuration = model.getControl(AnimControl.class).getAnimationLength(animationName); |
||||
this.channelIndex = channelIndex; |
||||
} |
||||
|
||||
/** |
||||
* 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 channelIndex the index of the channel default is 0. Events on the |
||||
* @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; |
||||
this.animationName = animationName; |
||||
this.loopMode = loopMode; |
||||
initialDuration = model.getControl(AnimControl.class).getAnimationLength(animationName); |
||||
this.channelIndex = channelIndex; |
||||
this.blendTime = blendTime; |
||||
} |
||||
|
||||
/** |
||||
* 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 initialDuration the initial duration of the event |
||||
* @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); |
||||
this.model = model; |
||||
this.animationName = animationName; |
||||
this.channelIndex = channelIndex; |
||||
} |
||||
|
||||
/** |
||||
* 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 initialDuration the initial duration of the event |
||||
* @param loopMode the loopMode |
||||
* @see LoopMode |
||||
* @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); |
||||
this.model = model; |
||||
this.animationName = animationName; |
||||
this.channelIndex = channelIndex; |
||||
} |
||||
|
||||
@Override |
||||
public void initEvent(Application app, Cinematic cinematic) { |
||||
super.initEvent(app, cinematic); |
||||
this.cinematic = cinematic; |
||||
if (channel == null) { |
||||
Object s = cinematic.getEventData(MODEL_CHANNELS, model); |
||||
if (s == null) { |
||||
s = new HashMap<Integer, AnimChannel>(); |
||||
int numChannels = model.getControl(AnimControl.class).getNumChannels(); |
||||
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); |
||||
} |
||||
|
||||
Map<Integer, AnimChannel> map = (Map<Integer, AnimChannel>) s; |
||||
this.channel = map.get(channelIndex); |
||||
if (this.channel == null) { |
||||
if (model == null) { |
||||
//the model is null we try to find it according to the name
|
||||
//this should occur only when loading an old saved cinematic
|
||||
//othewise it's an error
|
||||
model = cinematic.getScene().getChild(modelName); |
||||
} |
||||
if (model != null) { |
||||
channel = model.getControl(AnimControl.class).createChannel(); |
||||
map.put(channelIndex, channel); |
||||
} else { |
||||
//it's an error
|
||||
throw new UnsupportedOperationException("model should not be null"); |
||||
} |
||||
} |
||||
|
||||
} |
||||
} |
||||
|
||||
@Override |
||||
public void setTime(float time) { |
||||
super.setTime(time); |
||||
if (!animationName.equals(channel.getAnimationName())) { |
||||
channel.setAnim(animationName, blendTime); |
||||
} |
||||
float t = time; |
||||
if (loopMode == loopMode.Loop) { |
||||
t = t % channel.getAnimMaxTime(); |
||||
} |
||||
if (loopMode == loopMode.Cycle) { |
||||
float parity = (float) Math.ceil(time / channel.getAnimMaxTime()); |
||||
if (parity > 0 && parity % 2 == 0) { |
||||
t = channel.getAnimMaxTime() - t % channel.getAnimMaxTime(); |
||||
} else { |
||||
t = t % channel.getAnimMaxTime(); |
||||
} |
||||
|
||||
} |
||||
if (t < 0) { |
||||
channel.setTime(0); |
||||
channel.reset(true); |
||||
} |
||||
if (t > channel.getAnimMaxTime()) { |
||||
channel.setTime(t); |
||||
channel.getControl().update(0); |
||||
stop(); |
||||
} else { |
||||
channel.setTime(t); |
||||
channel.getControl().update(0); |
||||
} |
||||
|
||||
} |
||||
|
||||
@Override |
||||
public void onPlay() { |
||||
channel.getControl().setEnabled(true); |
||||
if (playState == PlayState.Stopped) { |
||||
channel.setAnim(animationName, blendTime); |
||||
channel.setSpeed(speed); |
||||
channel.setLoopMode(loopMode); |
||||
channel.setTime(0); |
||||
} |
||||
} |
||||
|
||||
@Override |
||||
public void setSpeed(float speed) { |
||||
super.setSpeed(speed); |
||||
if (channel != null) { |
||||
channel.setSpeed(speed); |
||||
} |
||||
} |
||||
|
||||
@Override |
||||
public void onUpdate(float tpf) { |
||||
} |
||||
|
||||
@Override |
||||
public void onStop() { |
||||
} |
||||
|
||||
@Override |
||||
public void forceStop() { |
||||
if (channel != null) { |
||||
channel.setTime(time); |
||||
channel.reset(false); |
||||
} |
||||
super.forceStop(); |
||||
} |
||||
|
||||
@Override |
||||
public void onPause() { |
||||
if (channel != null) { |
||||
channel.getControl().setEnabled(false); |
||||
} |
||||
} |
||||
|
||||
@Override |
||||
public void setLoopMode(LoopMode loopMode) { |
||||
super.setLoopMode(loopMode); |
||||
if (channel != null) { |
||||
channel.setLoopMode(loopMode); |
||||
} |
||||
} |
||||
|
||||
@Override |
||||
public void write(JmeExporter ex) throws IOException { |
||||
super.write(ex); |
||||
OutputCapsule oc = ex.getCapsule(this); |
||||
|
||||
oc.write(model, "model", null); |
||||
oc.write(animationName, "animationName", ""); |
||||
oc.write(blendTime, "blendTime", 0f); |
||||
oc.write(channelIndex, "channelIndex", 0); |
||||
|
||||
} |
||||
|
||||
@Override |
||||
public void read(JmeImporter im) throws IOException { |
||||
super.read(im); |
||||
InputCapsule ic = im.getCapsule(this); |
||||
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
|
||||
//scene sub scenegraph to find the correct instance of the model
|
||||
//This brings a reflaxion about the cinematic being an appstate,
|
||||
//shouldn't it be a control over the scene
|
||||
// this would allow to use the cloneForSpatial method and automatically
|
||||
//rebind cloned references of original objects.
|
||||
//for now as nobody probably ever saved a cinematic, this is not a critical issue
|
||||
model = (Spatial) ic.readSavable("model", null); |
||||
animationName = ic.readString("animationName", ""); |
||||
blendTime = ic.readFloat("blendTime", 0f); |
||||
channelIndex = ic.readInt("channelIndex", 0); |
||||
} |
||||
|
||||
@Override |
||||
public void dispose() { |
||||
super.dispose(); |
||||
if (cinematic != null) { |
||||
Object o = cinematic.getEventData(MODEL_CHANNELS, model); |
||||
if (o != null) { |
||||
Collection<AnimChannel> values = ((HashMap<Integer, AnimChannel>) o).values(); |
||||
while (values.remove(channel)); |
||||
if (values.isEmpty()) { |
||||
cinematic.removeEventData(MODEL_CHANNELS, model); |
||||
} |
||||
} |
||||
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 |
||||
* 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.animation.AnimationUtils; |
||||
import com.jme3.animation.LoopMode; |
||||
import com.jme3.app.Application; |
||||
import com.jme3.cinematic.Cinematic; |
||||
import com.jme3.cinematic.MotionPath; |
||||
import com.jme3.cinematic.PlayState; |
||||
import com.jme3.export.InputCapsule; |
||||
import com.jme3.export.JmeExporter; |
||||
import com.jme3.export.JmeImporter; |
||||
import com.jme3.export.OutputCapsule; |
||||
import com.jme3.math.Quaternion; |
||||
import com.jme3.math.Vector3f; |
||||
import com.jme3.renderer.RenderManager; |
||||
import com.jme3.renderer.ViewPort; |
||||
import com.jme3.scene.Spatial; |
||||
import com.jme3.scene.control.Control; |
||||
import com.jme3.util.clone.Cloner; |
||||
import com.jme3.util.clone.JmeCloneable; |
||||
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. |
||||
* |
||||
* You must first create a MotionPath and then create a MotionEvent to associate a spatial and the path. |
||||
* |
||||
* @author Nehon |
||||
*/ |
||||
public class MotionEvent extends AbstractCinematicEvent implements Control, JmeCloneable { |
||||
|
||||
protected Spatial spatial; |
||||
protected int currentWayPoint; |
||||
protected float currentValue; |
||||
protected Vector3f direction = new Vector3f(); |
||||
protected Vector3f lookAt = null; |
||||
protected Vector3f upVector = Vector3f.UNIT_Y; |
||||
protected Quaternion rotation = null; |
||||
protected Direction directionType = Direction.None; |
||||
protected MotionPath path; |
||||
private boolean isControl = true; |
||||
private int travelDirection = 1; |
||||
/** |
||||
* the distance traveled by the spatial on the path |
||||
*/ |
||||
protected float traveledDistance = 0; |
||||
|
||||
/** |
||||
* Enum for the different type of target direction behavior. |
||||
*/ |
||||
public enum Direction { |
||||
|
||||
/** |
||||
* The target stays in the starting direction. |
||||
*/ |
||||
None, |
||||
/** |
||||
* The target rotates with the direction of the path. |
||||
*/ |
||||
Path, |
||||
/** |
||||
* 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. |
||||
*/ |
||||
PathAndRotation, |
||||
/** |
||||
* The target rotates with the given rotation. |
||||
*/ |
||||
Rotation, |
||||
/** |
||||
* The target looks at a point. |
||||
* You need to use the setLookAt method when using this direction. |
||||
*/ |
||||
LookAt |
||||
} |
||||
|
||||
/** |
||||
* Create MotionEvent, |
||||
* when using this constructor don't forget to assign spatial and path. |
||||
*/ |
||||
public MotionEvent() { |
||||
super(); |
||||
} |
||||
|
||||
/** |
||||
* Creates a MotionPath for the given spatial on the given motion path. |
||||
* @param spatial |
||||
* @param path |
||||
*/ |
||||
public MotionEvent(Spatial spatial, MotionPath path) { |
||||
super(); |
||||
spatial.addControl(this); |
||||
this.path = path; |
||||
} |
||||
|
||||
/** |
||||
* Creates a MotionPath for the given spatial on the given motion path. |
||||
* @param spatial |
||||
* @param path |
||||
*/ |
||||
public MotionEvent(Spatial spatial, MotionPath path, float initialDuration) { |
||||
super(initialDuration); |
||||
spatial.addControl(this); |
||||
this.path = path; |
||||
} |
||||
|
||||
/** |
||||
* Creates a MotionPath for the given spatial on the given motion path. |
||||
* @param spatial |
||||
* @param path |
||||
*/ |
||||
public MotionEvent(Spatial spatial, MotionPath path, LoopMode loopMode) { |
||||
super(); |
||||
spatial.addControl(this); |
||||
this.path = path; |
||||
this.loopMode = loopMode; |
||||
} |
||||
|
||||
/** |
||||
* Creates a MotionPath for the given spatial on the given motion path. |
||||
* @param spatial |
||||
* @param path |
||||
*/ |
||||
public MotionEvent(Spatial spatial, MotionPath path, float initialDuration, LoopMode loopMode) { |
||||
super(initialDuration); |
||||
spatial.addControl(this); |
||||
this.path = path; |
||||
this.loopMode = loopMode; |
||||
} |
||||
|
||||
public void update(float tpf) { |
||||
if (isControl) { |
||||
internalUpdate(tpf); |
||||
} |
||||
} |
||||
|
||||
@Override |
||||
public void internalUpdate(float tpf) { |
||||
if (playState == PlayState.Playing) { |
||||
time = time + (tpf * speed); |
||||
if (loopMode == LoopMode.Loop && time < 0) { |
||||
time = initialDuration; |
||||
} |
||||
if ((time >= initialDuration || time < 0) && loopMode == LoopMode.DontLoop) { |
||||
if (time >= initialDuration) { |
||||
path.triggerWayPointReach(path.getNbWayPoints() - 1, this); |
||||
} |
||||
stop(); |
||||
} else { |
||||
time = AnimationUtils.clampWrapTime(time, initialDuration, loopMode); |
||||
if(time<0){ |
||||
speed = - speed; |
||||
time = - time; |
||||
} |
||||
onUpdate(tpf); |
||||
} |
||||
} |
||||
} |
||||
|
||||
@Override |
||||
public void initEvent(Application app, Cinematic cinematic) { |
||||
super.initEvent(app, cinematic); |
||||
isControl = false; |
||||
} |
||||
|
||||
@Override |
||||
public void setTime(float time) { |
||||
super.setTime(time); |
||||
onUpdate(0); |
||||
} |
||||
|
||||
public void onUpdate(float tpf) { |
||||
traveledDistance = path.interpolatePath(time, this, tpf); |
||||
computeTargetDirection(); |
||||
} |
||||
|
||||
@Override |
||||
public void write(JmeExporter ex) throws IOException { |
||||
super.write(ex); |
||||
OutputCapsule oc = ex.getCapsule(this); |
||||
oc.write(lookAt, "lookAt", null); |
||||
oc.write(upVector, "upVector", Vector3f.UNIT_Y); |
||||
oc.write(rotation, "rotation", null); |
||||
oc.write(directionType, "directionType", Direction.None); |
||||
oc.write(path, "path", null); |
||||
oc.write(spatial, "spatial", null); |
||||
} |
||||
|
||||
@Override |
||||
public void read(JmeImporter im) throws IOException { |
||||
super.read(im); |
||||
InputCapsule in = im.getCapsule(this); |
||||
lookAt = (Vector3f) in.readSavable("lookAt", null); |
||||
upVector = (Vector3f) in.readSavable("upVector", Vector3f.UNIT_Y); |
||||
rotation = (Quaternion) in.readSavable("rotation", null); |
||||
directionType = in.readEnum("directionType", Direction.class, Direction.None); |
||||
path = (MotionPath) in.readSavable("path", null); |
||||
spatial = (Spatial) in.readSavable("spatial", null); |
||||
} |
||||
|
||||
/** |
||||
* This method is meant to be called by the motion path only. |
||||
* @return |
||||
*/ |
||||
public boolean needsDirection() { |
||||
return directionType == Direction.Path || directionType == Direction.PathAndRotation; |
||||
} |
||||
|
||||
private void computeTargetDirection() { |
||||
switch (directionType) { |
||||
case Path: |
||||
Quaternion q = new Quaternion(); |
||||
q.lookAt(direction, upVector); |
||||
spatial.setLocalRotation(q); |
||||
break; |
||||
case LookAt: |
||||
if (lookAt != null) { |
||||
spatial.lookAt(lookAt, upVector); |
||||
} |
||||
break; |
||||
case PathAndRotation: |
||||
if (rotation != null) { |
||||
Quaternion q2 = new Quaternion(); |
||||
q2.lookAt(direction, upVector); |
||||
q2.multLocal(rotation); |
||||
spatial.setLocalRotation(q2); |
||||
} |
||||
break; |
||||
case Rotation: |
||||
if (rotation != null) { |
||||
spatial.setLocalRotation(rotation); |
||||
} |
||||
break; |
||||
case None: |
||||
break; |
||||
default: |
||||
break; |
||||
} |
||||
} |
||||
|
||||
/** |
||||
* Clone this control for the given spatial. |
||||
* @param spatial |
||||
* @return |
||||
*/ |
||||
@Override |
||||
public Control cloneForSpatial(Spatial spatial) { |
||||
MotionEvent control = new MotionEvent(); |
||||
control.setPath(path); |
||||
control.playState = playState; |
||||
control.currentWayPoint = currentWayPoint; |
||||
control.currentValue = currentValue; |
||||
control.direction = direction.clone(); |
||||
control.lookAt = lookAt; |
||||
control.upVector = upVector.clone(); |
||||
control.rotation = rotation; |
||||
control.initialDuration = initialDuration; |
||||
control.speed = speed; |
||||
control.loopMode = loopMode; |
||||
control.directionType = directionType; |
||||
|
||||
return control; |
||||
} |
||||
|
||||
@Override |
||||
public Object jmeClone() { |
||||
MotionEvent control = new MotionEvent(); |
||||
control.path = path; |
||||
control.playState = playState; |
||||
control.currentWayPoint = currentWayPoint; |
||||
control.currentValue = currentValue; |
||||
control.direction = direction.clone(); |
||||
control.lookAt = lookAt; |
||||
control.upVector = upVector.clone(); |
||||
control.rotation = rotation; |
||||
control.initialDuration = initialDuration; |
||||
control.speed = speed; |
||||
control.loopMode = loopMode; |
||||
control.directionType = directionType; |
||||
control.spatial = spatial; |
||||
|
||||
return control; |
||||
} |
||||
|
||||
@Override |
||||
public void cloneFields( Cloner cloner, Object original ) { |
||||
this.spatial = cloner.clone(spatial); |
||||
} |
||||
|
||||
@Override |
||||
public void onPlay() { |
||||
traveledDistance = 0; |
||||
} |
||||
|
||||
@Override |
||||
public void onStop() { |
||||
currentWayPoint = 0; |
||||
} |
||||
|
||||
@Override |
||||
public void onPause() { |
||||
} |
||||
|
||||
/** |
||||
* This method is meant to be called by the motion path only. |
||||
* @return |
||||
*/ |
||||
public float getCurrentValue() { |
||||
return currentValue; |
||||
} |
||||
|
||||
/** |
||||
* This method is meant to be called by the motion path only. |
||||
* |
||||
*/ |
||||
public void setCurrentValue(float currentValue) { |
||||
this.currentValue = currentValue; |
||||
} |
||||
|
||||
/** |
||||
* This method is meant to be called by the motion path only. |
||||
* @return |
||||
*/ |
||||
public int getCurrentWayPoint() { |
||||
return currentWayPoint; |
||||
} |
||||
|
||||
/** |
||||
* This method is meant to be called by the motion path only. |
||||
* |
||||
*/ |
||||
public void setCurrentWayPoint(int currentWayPoint) { |
||||
this.currentWayPoint = currentWayPoint; |
||||
} |
||||
|
||||
/** |
||||
* Returns the direction the spatial is moving. |
||||
* @return |
||||
*/ |
||||
public Vector3f getDirection() { |
||||
return direction; |
||||
} |
||||
|
||||
/** |
||||
* Sets the direction of the spatial, using the Y axis as the up vector. |
||||
* Use MotionEvent#setDirection((Vector3f direction,Vector3f upVector) if |
||||
* you want a custum up vector. |
||||
* This method is used by the motion path. |
||||
* @param direction |
||||
*/ |
||||
public void setDirection(Vector3f direction) { |
||||
setDirection(direction, Vector3f.UNIT_Y); |
||||
} |
||||
|
||||
/** |
||||
* Sets the direction of the spatial with the given up vector. |
||||
* This method is used by the motion path. |
||||
* @param direction |
||||
* @param upVector the up vector to consider for this direction. |
||||
*/ |
||||
public void setDirection(Vector3f direction,Vector3f upVector) { |
||||
this.direction.set(direction); |
||||
this.upVector.set(upVector); |
||||
} |
||||
|
||||
/** |
||||
* Returns the direction type of the target. |
||||
* @return the direction type. |
||||
*/ |
||||
public Direction getDirectionType() { |
||||
return directionType; |
||||
} |
||||
|
||||
/** |
||||
* Sets the direction type of the target. |
||||
* On each update the direction given to the target can have different behavior. |
||||
* See the Direction Enum for explanations. |
||||
* @param directionType the direction type. |
||||
*/ |
||||
public void setDirectionType(Direction directionType) { |
||||
this.directionType = directionType; |
||||
} |
||||
|
||||
/** |
||||
* Set the lookAt for the target. |
||||
* This can be used only if direction Type is Direction.LookAt. |
||||
* @param lookAt the position to look at. |
||||
* @param upVector the up vector. |
||||
*/ |
||||
public void setLookAt(Vector3f lookAt, Vector3f upVector) { |
||||
this.lookAt = lookAt; |
||||
this.upVector = upVector; |
||||
} |
||||
|
||||
/** |
||||
* Returns the rotation of the target. |
||||
* @return the rotation quaternion. |
||||
*/ |
||||
public Quaternion getRotation() { |
||||
return rotation; |
||||
} |
||||
|
||||
/** |
||||
* Sets the rotation of the target. |
||||
* 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 Rotation the rotation of the target will be set with the given Quaternion. |
||||
* @param rotation the rotation quaternion. |
||||
*/ |
||||
public void setRotation(Quaternion rotation) { |
||||
this.rotation = rotation; |
||||
} |
||||
|
||||
/** |
||||
* Return the motion path this control follows. |
||||
* @return |
||||
*/ |
||||
public MotionPath getPath() { |
||||
return path; |
||||
} |
||||
|
||||
/** |
||||
* Sets the motion path to follow. |
||||
* @param path |
||||
*/ |
||||
public void setPath(MotionPath path) { |
||||
this.path = path; |
||||
} |
||||
|
||||
public void setEnabled(boolean enabled) { |
||||
if (enabled) { |
||||
play(); |
||||
} else { |
||||
pause(); |
||||
} |
||||
} |
||||
|
||||
public boolean isEnabled() { |
||||
return playState != PlayState.Stopped; |
||||
} |
||||
|
||||
public void render(RenderManager rm, ViewPort vp) { |
||||
} |
||||
|
||||
public void setSpatial(Spatial spatial) { |
||||
this.spatial = spatial; |
||||
} |
||||
|
||||
public Spatial getSpatial() { |
||||
return spatial; |
||||
} |
||||
|
||||
/** |
||||
* Return the distance traveled by the spatial on the path. |
||||
* @return |
||||
*/ |
||||
public float getTraveledDistance() { |
||||
return traveledDistance; |
||||
} |
||||
} |
||||
/* |
||||
* Copyright (c) 2009-2016 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.animation.AnimationUtils; |
||||
import com.jme3.animation.LoopMode; |
||||
import com.jme3.app.Application; |
||||
import com.jme3.cinematic.Cinematic; |
||||
import com.jme3.cinematic.MotionPath; |
||||
import com.jme3.cinematic.PlayState; |
||||
import com.jme3.export.InputCapsule; |
||||
import com.jme3.export.JmeExporter; |
||||
import com.jme3.export.JmeImporter; |
||||
import com.jme3.export.OutputCapsule; |
||||
import com.jme3.math.Quaternion; |
||||
import com.jme3.math.Vector3f; |
||||
import com.jme3.renderer.RenderManager; |
||||
import com.jme3.renderer.ViewPort; |
||||
import com.jme3.scene.Spatial; |
||||
import com.jme3.scene.control.Control; |
||||
import com.jme3.util.clone.Cloner; |
||||
import com.jme3.util.clone.JmeCloneable; |
||||
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. |
||||
* |
||||
* You must first create a MotionPath and then create a MotionEvent to associate a spatial and the path. |
||||
* |
||||
* @author Nehon |
||||
*/ |
||||
public class MotionEvent extends AbstractCinematicEvent implements Control, JmeCloneable { |
||||
|
||||
protected Spatial spatial; |
||||
protected int currentWayPoint; |
||||
protected float currentValue; |
||||
protected Vector3f direction = new Vector3f(); |
||||
protected Vector3f lookAt = null; |
||||
protected Vector3f upVector = Vector3f.UNIT_Y; |
||||
protected Quaternion rotation = null; |
||||
protected Direction directionType = Direction.None; |
||||
protected MotionPath path; |
||||
private boolean isControl = true; |
||||
private int travelDirection = 1; |
||||
/** |
||||
* the distance traveled by the spatial on the path |
||||
*/ |
||||
protected float traveledDistance = 0; |
||||
|
||||
/** |
||||
* Enum for the different type of target direction behavior. |
||||
*/ |
||||
public enum Direction { |
||||
|
||||
/** |
||||
* The target stays in the starting direction. |
||||
*/ |
||||
None, |
||||
/** |
||||
* The target rotates with the direction of the path. |
||||
*/ |
||||
Path, |
||||
/** |
||||
* 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. |
||||
*/ |
||||
PathAndRotation, |
||||
/** |
||||
* The target rotates with the given rotation. |
||||
*/ |
||||
Rotation, |
||||
/** |
||||
* The target looks at a point. |
||||
* You need to use the setLookAt method when using this direction. |
||||
*/ |
||||
LookAt |
||||
} |
||||
|
||||
/** |
||||
* Create MotionEvent, |
||||
* when using this constructor don't forget to assign spatial and path. |
||||
*/ |
||||
public MotionEvent() { |
||||
super(); |
||||
} |
||||
|
||||
/** |
||||
* Creates a MotionPath for the given spatial on the given motion path. |
||||
* @param spatial |
||||
* @param path |
||||
*/ |
||||
public MotionEvent(Spatial spatial, MotionPath path) { |
||||
super(); |
||||
spatial.addControl(this); |
||||
this.path = path; |
||||
} |
||||
|
||||
/** |
||||
* Creates a MotionPath for the given spatial on the given motion path. |
||||
* @param spatial |
||||
* @param path |
||||
*/ |
||||
public MotionEvent(Spatial spatial, MotionPath path, float initialDuration) { |
||||
super(initialDuration); |
||||
spatial.addControl(this); |
||||
this.path = path; |
||||
} |
||||
|
||||
/** |
||||
* Creates a MotionPath for the given spatial on the given motion path. |
||||
* @param spatial |
||||
* @param path |
||||
*/ |
||||
public MotionEvent(Spatial spatial, MotionPath path, LoopMode loopMode) { |
||||
super(); |
||||
spatial.addControl(this); |
||||
this.path = path; |
||||
this.loopMode = loopMode; |
||||
} |
||||
|
||||
/** |
||||
* Creates a MotionPath for the given spatial on the given motion path. |
||||
* @param spatial |
||||
* @param path |
||||
*/ |
||||
public MotionEvent(Spatial spatial, MotionPath path, float initialDuration, LoopMode loopMode) { |
||||
super(initialDuration); |
||||
spatial.addControl(this); |
||||
this.path = path; |
||||
this.loopMode = loopMode; |
||||
} |
||||
|
||||
public void update(float tpf) { |
||||
if (isControl) { |
||||
internalUpdate(tpf); |
||||
} |
||||
} |
||||
|
||||
@Override |
||||
public void internalUpdate(float tpf) { |
||||
if (playState == PlayState.Playing) { |
||||
time = time + (tpf * speed); |
||||
if (loopMode == LoopMode.Loop && time < 0) { |
||||
time = initialDuration; |
||||
} |
||||
if ((time >= initialDuration || time < 0) && loopMode == LoopMode.DontLoop) { |
||||
if (time >= initialDuration) { |
||||
path.triggerWayPointReach(path.getNbWayPoints() - 1, this); |
||||
} |
||||
stop(); |
||||
} else { |
||||
time = AnimationUtils.clampWrapTime(time, initialDuration, loopMode); |
||||
if(time<0){ |
||||
speed = - speed; |
||||
time = - time; |
||||
} |
||||
onUpdate(tpf); |
||||
} |
||||
} |
||||
} |
||||
|
||||
@Override |
||||
public void initEvent(Application app, Cinematic cinematic) { |
||||
super.initEvent(app, cinematic); |
||||
isControl = false; |
||||
} |
||||
|
||||
@Override |
||||
public void setTime(float time) { |
||||
super.setTime(time); |
||||
onUpdate(0); |
||||
} |
||||
|
||||
public void onUpdate(float tpf) { |
||||
traveledDistance = path.interpolatePath(time, this, tpf); |
||||
computeTargetDirection(); |
||||
} |
||||
|
||||
@Override |
||||
public void write(JmeExporter ex) throws IOException { |
||||
super.write(ex); |
||||
OutputCapsule oc = ex.getCapsule(this); |
||||
oc.write(lookAt, "lookAt", null); |
||||
oc.write(upVector, "upVector", Vector3f.UNIT_Y); |
||||
oc.write(rotation, "rotation", null); |
||||
oc.write(directionType, "directionType", Direction.None); |
||||
oc.write(path, "path", null); |
||||
oc.write(spatial, "spatial", null); |
||||
} |
||||
|
||||
@Override |
||||
public void read(JmeImporter im) throws IOException { |
||||
super.read(im); |
||||
InputCapsule in = im.getCapsule(this); |
||||
lookAt = (Vector3f) in.readSavable("lookAt", null); |
||||
upVector = (Vector3f) in.readSavable("upVector", Vector3f.UNIT_Y); |
||||
rotation = (Quaternion) in.readSavable("rotation", null); |
||||
directionType = in.readEnum("directionType", Direction.class, Direction.None); |
||||
path = (MotionPath) in.readSavable("path", null); |
||||
spatial = (Spatial) in.readSavable("spatial", null); |
||||
} |
||||
|
||||
/** |
||||
* This method is meant to be called by the motion path only. |
||||
* @return |
||||
*/ |
||||
public boolean needsDirection() { |
||||
return directionType == Direction.Path || directionType == Direction.PathAndRotation; |
||||
} |
||||
|
||||
private void computeTargetDirection() { |
||||
switch (directionType) { |
||||
case Path: |
||||
Quaternion q = new Quaternion(); |
||||
q.lookAt(direction, upVector); |
||||
spatial.setLocalRotation(q); |
||||
break; |
||||
case LookAt: |
||||
if (lookAt != null) { |
||||
spatial.lookAt(lookAt, upVector); |
||||
} |
||||
break; |
||||
case PathAndRotation: |
||||
if (rotation != null) { |
||||
Quaternion q2 = new Quaternion(); |
||||
q2.lookAt(direction, upVector); |
||||
q2.multLocal(rotation); |
||||
spatial.setLocalRotation(q2); |
||||
} |
||||
break; |
||||
case Rotation: |
||||
if (rotation != null) { |
||||
spatial.setLocalRotation(rotation); |
||||
} |
||||
break; |
||||
case None: |
||||
break; |
||||
default: |
||||
break; |
||||
} |
||||
} |
||||
|
||||
/** |
||||
* Clone this control for the given spatial. |
||||
* @param spatial |
||||
* @return |
||||
*/ |
||||
@Override |
||||
public Control cloneForSpatial(Spatial spatial) { |
||||
MotionEvent control = new MotionEvent(); |
||||
control.setPath(path); |
||||
control.playState = playState; |
||||
control.currentWayPoint = currentWayPoint; |
||||
control.currentValue = currentValue; |
||||
control.direction = direction.clone(); |
||||
control.lookAt = lookAt; |
||||
control.upVector = upVector.clone(); |
||||
control.rotation = rotation; |
||||
control.initialDuration = initialDuration; |
||||
control.speed = speed; |
||||
control.loopMode = loopMode; |
||||
control.directionType = directionType; |
||||
|
||||
return control; |
||||
} |
||||
|
||||
@Override |
||||
public Object jmeClone() { |
||||
MotionEvent control = new MotionEvent(); |
||||
control.path = path; |
||||
control.playState = playState; |
||||
control.currentWayPoint = currentWayPoint; |
||||
control.currentValue = currentValue; |
||||
control.direction = direction.clone(); |
||||
control.lookAt = lookAt; |
||||
control.upVector = upVector.clone(); |
||||
control.rotation = rotation; |
||||
control.initialDuration = initialDuration; |
||||
control.speed = speed; |
||||
control.loopMode = loopMode; |
||||
control.directionType = directionType; |
||||
control.spatial = spatial; |
||||
|
||||
return control; |
||||
} |
||||
|
||||
@Override |
||||
public void cloneFields( Cloner cloner, Object original ) { |
||||
this.spatial = cloner.clone(spatial); |
||||
} |
||||
|
||||
@Override |
||||
public void onPlay() { |
||||
traveledDistance = 0; |
||||
} |
||||
|
||||
@Override |
||||
public void onStop() { |
||||
currentWayPoint = 0; |
||||
} |
||||
|
||||
@Override |
||||
public void onPause() { |
||||
} |
||||
|
||||
/** |
||||
* This method is meant to be called by the motion path only. |
||||
* @return |
||||
*/ |
||||
public float getCurrentValue() { |
||||
return currentValue; |
||||
} |
||||
|
||||
/** |
||||
* This method is meant to be called by the motion path only. |
||||
* |
||||
*/ |
||||
public void setCurrentValue(float currentValue) { |
||||
this.currentValue = currentValue; |
||||
} |
||||
|
||||
/** |
||||
* This method is meant to be called by the motion path only. |
||||
* @return |
||||
*/ |
||||
public int getCurrentWayPoint() { |
||||
return currentWayPoint; |
||||
} |
||||
|
||||
/** |
||||
* This method is meant to be called by the motion path only. |
||||
* |
||||
*/ |
||||
public void setCurrentWayPoint(int currentWayPoint) { |
||||
this.currentWayPoint = currentWayPoint; |
||||
} |
||||
|
||||
/** |
||||
* Returns the direction the spatial is moving. |
||||
* @return |
||||
*/ |
||||
public Vector3f getDirection() { |
||||
return direction; |
||||
} |
||||
|
||||
/** |
||||
* Sets the direction of the spatial, using the Y axis as the up vector. |
||||
* Use MotionEvent#setDirection((Vector3f direction,Vector3f upVector) if |
||||
* you want a custum up vector. |
||||
* This method is used by the motion path. |
||||
* @param direction |
||||
*/ |
||||
public void setDirection(Vector3f direction) { |
||||
setDirection(direction, Vector3f.UNIT_Y); |
||||
} |
||||
|
||||
/** |
||||
* Sets the direction of the spatial with the given up vector. |
||||
* This method is used by the motion path. |
||||
* @param direction |
||||
* @param upVector the up vector to consider for this direction. |
||||
*/ |
||||
public void setDirection(Vector3f direction,Vector3f upVector) { |
||||
this.direction.set(direction); |
||||
this.upVector.set(upVector); |
||||
} |
||||
|
||||
/** |
||||
* Returns the direction type of the target. |
||||
* @return the direction type. |
||||
*/ |
||||
public Direction getDirectionType() { |
||||
return directionType; |
||||
} |
||||
|
||||
/** |
||||
* Sets the direction type of the target. |
||||
* On each update the direction given to the target can have different behavior. |
||||
* See the Direction Enum for explanations. |
||||
* @param directionType the direction type. |
||||
*/ |
||||
public void setDirectionType(Direction directionType) { |
||||
this.directionType = directionType; |
||||
} |
||||
|
||||
/** |
||||
* Set the lookAt for the target. |
||||
* This can be used only if direction Type is Direction.LookAt. |
||||
* @param lookAt the position to look at. |
||||
* @param upVector the up vector. |
||||
*/ |
||||
public void setLookAt(Vector3f lookAt, Vector3f upVector) { |
||||
this.lookAt = lookAt; |
||||
this.upVector = upVector; |
||||
} |
||||
|
||||
/** |
||||
* Returns the rotation of the target. |
||||
* @return the rotation quaternion. |
||||
*/ |
||||
public Quaternion getRotation() { |
||||
return rotation; |
||||
} |
||||
|
||||
/** |
||||
* Sets the rotation of the target. |
||||
* 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 Rotation the rotation of the target will be set with the given Quaternion. |
||||
* @param rotation the rotation quaternion. |
||||
*/ |
||||
public void setRotation(Quaternion rotation) { |
||||
this.rotation = rotation; |
||||
} |
||||
|
||||
/** |
||||
* Return the motion path this control follows. |
||||
* @return |
||||
*/ |
||||
public MotionPath getPath() { |
||||
return path; |
||||
} |
||||
|
||||
/** |
||||
* Sets the motion path to follow. |
||||
* @param path |
||||
*/ |
||||
public void setPath(MotionPath path) { |
||||
this.path = path; |
||||
} |
||||
|
||||
public void setEnabled(boolean enabled) { |
||||
if (enabled) { |
||||
play(); |
||||
} else { |
||||
pause(); |
||||
} |
||||
} |
||||
|
||||
public boolean isEnabled() { |
||||
return playState != PlayState.Stopped; |
||||
} |
||||
|
||||
public void render(RenderManager rm, ViewPort vp) { |
||||
} |
||||
|
||||
public void setSpatial(Spatial spatial) { |
||||
this.spatial = spatial; |
||||
} |
||||
|
||||
public Spatial getSpatial() { |
||||
return spatial; |
||||
} |
||||
|
||||
/** |
||||
* Return the distance traveled by the spatial on the path. |
||||
* @return |
||||
*/ |
||||
public float getTraveledDistance() { |
||||
return traveledDistance; |
||||
} |
||||
} |
||||
|
@ -1,229 +1,230 @@ |
||||
/* |
||||
* Copyright (c) 2009-2012 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.animation.LoopMode; |
||||
import com.jme3.app.Application; |
||||
import com.jme3.audio.AudioNode; |
||||
import com.jme3.audio.AudioSource; |
||||
import com.jme3.cinematic.Cinematic; |
||||
import com.jme3.export.InputCapsule; |
||||
import com.jme3.export.JmeExporter; |
||||
import com.jme3.export.JmeImporter; |
||||
import com.jme3.export.OutputCapsule; |
||||
import java.io.IOException; |
||||
|
||||
/** |
||||
* A sound track to be played in a cinematic. |
||||
* @author Nehon |
||||
*/ |
||||
public class SoundEvent extends AbstractCinematicEvent { |
||||
|
||||
protected String path; |
||||
protected AudioNode audioNode; |
||||
protected boolean stream = false; |
||||
|
||||
/** |
||||
* creates a sound track from the given resource path |
||||
* @param path the path to an audio file (ie : "Sounds/mySound.wav") |
||||
*/ |
||||
public SoundEvent(String path) { |
||||
this.path = path; |
||||
} |
||||
|
||||
/** |
||||
* creates a sound track from the given resource path |
||||
* @param path the path to an audio file (ie : "Sounds/mySound.wav") |
||||
* @param stream true to make the audio data streamed |
||||
*/ |
||||
public SoundEvent(String path, boolean stream) { |
||||
this(path); |
||||
this.stream = stream; |
||||
} |
||||
|
||||
/** |
||||
* creates a sound track from the given resource path |
||||
* @param path the path to an audio file (ie : "Sounds/mySound.wav") |
||||
* @param stream true to make the audio data streamed |
||||
* @param initialDuration the initial duration of the event |
||||
*/ |
||||
public SoundEvent(String path, boolean stream, float initialDuration) { |
||||
super(initialDuration); |
||||
this.path = path; |
||||
this.stream = stream; |
||||
} |
||||
|
||||
/** |
||||
* creates a sound track from the given resource path |
||||
* @param path the path to an audio file (ie : "Sounds/mySound.wav") |
||||
* @param stream true to make the audio data streamed |
||||
* @param loopMode the loopMode |
||||
* @see LoopMode |
||||
*/ |
||||
public SoundEvent(String path, boolean stream, LoopMode loopMode) { |
||||
super(loopMode); |
||||
this.path = path; |
||||
this.stream = stream; |
||||
} |
||||
|
||||
/** |
||||
* creates a sound track from the given resource path |
||||
* @param path the path to an audio file (ie : "Sounds/mySound.wav") |
||||
* @param stream true to make the audio data streamed |
||||
* @param initialDuration the initial duration of the event |
||||
* @param loopMode the loopMode |
||||
* @see LoopMode |
||||
*/ |
||||
public SoundEvent(String path, boolean stream, float initialDuration, LoopMode loopMode) { |
||||
super(initialDuration, loopMode); |
||||
this.path = path; |
||||
this.stream = stream; |
||||
} |
||||
|
||||
/** |
||||
* creates a sound track from the given resource path |
||||
* @param path the path to an audio file (ie : "Sounds/mySound.wav") |
||||
* @param initialDuration the initial duration of the event |
||||
*/ |
||||
public SoundEvent(String path, float initialDuration) { |
||||
super(initialDuration); |
||||
this.path = path; |
||||
} |
||||
|
||||
/** |
||||
* creates a sound track from the given resource path |
||||
* @param path the path to an audio file (ie : "Sounds/mySound.wav") |
||||
* @param loopMode the loopMode |
||||
* @see LoopMode |
||||
*/ |
||||
public SoundEvent(String path, LoopMode loopMode) { |
||||
super(loopMode); |
||||
this.path = path; |
||||
} |
||||
|
||||
/** |
||||
* creates a sound track from the given resource path |
||||
* @param path the path to an audio file (ie : "Sounds/mySound.wav") |
||||
* @param initialDuration the initial duration of the event |
||||
* @param loopMode the loopMode |
||||
* @see LoopMode |
||||
*/ |
||||
public SoundEvent(String path, float initialDuration, LoopMode loopMode) { |
||||
super(initialDuration, loopMode); |
||||
this.path = path; |
||||
} |
||||
|
||||
/** |
||||
* creates a sound event |
||||
* used for serialization |
||||
*/ |
||||
public SoundEvent() { |
||||
} |
||||
|
||||
@Override |
||||
public void initEvent(Application app, Cinematic cinematic) { |
||||
super.initEvent(app, cinematic); |
||||
audioNode = new AudioNode(app.getAssetManager(), path, stream); |
||||
audioNode.setPositional(false); |
||||
setLoopMode(loopMode); |
||||
} |
||||
|
||||
@Override |
||||
public void setTime(float time) { |
||||
super.setTime(time); |
||||
//can occur on rewind
|
||||
if (time < 0f) { |
||||
stop(); |
||||
}else{ |
||||
audioNode.setTimeOffset(time); |
||||
} |
||||
} |
||||
|
||||
@Override |
||||
public void onPlay() { |
||||
audioNode.play(); |
||||
} |
||||
|
||||
@Override |
||||
public void onStop() { |
||||
audioNode.stop(); |
||||
|
||||
} |
||||
|
||||
@Override |
||||
public void onPause() { |
||||
audioNode.pause(); |
||||
} |
||||
|
||||
@Override |
||||
public void onUpdate(float tpf) { |
||||
if (audioNode.getStatus() == AudioSource.Status.Stopped) { |
||||
stop(); |
||||
} |
||||
} |
||||
|
||||
/** |
||||
* Returns the underlying audio node of this sound track |
||||
* @return |
||||
*/ |
||||
public AudioNode getAudioNode() { |
||||
return audioNode; |
||||
} |
||||
|
||||
@Override |
||||
public void setLoopMode(LoopMode loopMode) { |
||||
super.setLoopMode(loopMode); |
||||
|
||||
if (loopMode != LoopMode.DontLoop) { |
||||
audioNode.setLooping(true); |
||||
} else { |
||||
audioNode.setLooping(false); |
||||
} |
||||
} |
||||
|
||||
@Override |
||||
public void write(JmeExporter ex) throws IOException { |
||||
super.write(ex); |
||||
OutputCapsule oc = ex.getCapsule(this); |
||||
oc.write(path, "path", ""); |
||||
oc.write(stream, "stream", false); |
||||
} |
||||
|
||||
@Override |
||||
public void read(JmeImporter im) throws IOException { |
||||
super.read(im); |
||||
InputCapsule ic = im.getCapsule(this); |
||||
path = ic.readString("path", ""); |
||||
stream = ic.readBoolean("stream", false); |
||||
|
||||
} |
||||
} |
||||
/* |
||||
* Copyright (c) 2009-2012 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.animation.LoopMode; |
||||
import com.jme3.app.Application; |
||||
import com.jme3.audio.AudioNode; |
||||
import com.jme3.audio.AudioSource; |
||||
import com.jme3.cinematic.Cinematic; |
||||
import com.jme3.export.InputCapsule; |
||||
import com.jme3.export.JmeExporter; |
||||
import com.jme3.export.JmeImporter; |
||||
import com.jme3.export.OutputCapsule; |
||||
import java.io.IOException; |
||||
|
||||
/** |
||||
* A sound track to be played in a cinematic. |
||||
* @author Nehon |
||||
*/ |
||||
public class SoundEvent extends AbstractCinematicEvent { |
||||
|
||||
protected String path; |
||||
protected AudioNode audioNode; |
||||
protected boolean stream = false; |
||||
|
||||
/** |
||||
* creates a sound track from the given resource path |
||||
* @param path the path to an audio file (ie : "Sounds/mySound.wav") |
||||
*/ |
||||
public SoundEvent(String path) { |
||||
this.path = path; |
||||
} |
||||
|
||||
/** |
||||
* creates a sound track from the given resource path |
||||
* @param path the path to an audio file (ie : "Sounds/mySound.wav") |
||||
* @param stream true to make the audio data streamed |
||||
*/ |
||||
public SoundEvent(String path, boolean stream) { |
||||
this(path); |
||||
this.stream = stream; |
||||
} |
||||
|
||||
/** |
||||
* creates a sound track from the given resource path |
||||
* @param path the path to an audio file (ie : "Sounds/mySound.wav") |
||||
* @param stream true to make the audio data streamed |
||||
* @param initialDuration the initial duration of the event |
||||
*/ |
||||
public SoundEvent(String path, boolean stream, float initialDuration) { |
||||
super(initialDuration); |
||||
this.path = path; |
||||
this.stream = stream; |
||||
} |
||||
|
||||
/** |
||||
* creates a sound track from the given resource path |
||||
* @param path the path to an audio file (ie : "Sounds/mySound.wav") |
||||
* @param stream true to make the audio data streamed |
||||
* @param loopMode the loopMode |
||||
* @see LoopMode |
||||
*/ |
||||
public SoundEvent(String path, boolean stream, LoopMode loopMode) { |
||||
super(loopMode); |
||||
this.path = path; |
||||
this.stream = stream; |
||||
} |
||||
|
||||
/** |
||||
* creates a sound track from the given resource path |
||||
* @param path the path to an audio file (ie : "Sounds/mySound.wav") |
||||
* @param stream true to make the audio data streamed |
||||
* @param initialDuration the initial duration of the event |
||||
* @param loopMode the loopMode |
||||
* @see LoopMode |
||||
*/ |
||||
public SoundEvent(String path, boolean stream, float initialDuration, LoopMode loopMode) { |
||||
super(initialDuration, loopMode); |
||||
this.path = path; |
||||
this.stream = stream; |
||||
} |
||||
|
||||
/** |
||||
* creates a sound track from the given resource path |
||||
* @param path the path to an audio file (ie : "Sounds/mySound.wav") |
||||
* @param initialDuration the initial duration of the event |
||||
*/ |
||||
public SoundEvent(String path, float initialDuration) { |
||||
super(initialDuration); |
||||
this.path = path; |
||||
} |
||||
|
||||
/** |
||||
* creates a sound track from the given resource path |
||||
* @param path the path to an audio file (ie : "Sounds/mySound.wav") |
||||
* @param loopMode the loopMode |
||||
* @see LoopMode |
||||
*/ |
||||
public SoundEvent(String path, LoopMode loopMode) { |
||||
super(loopMode); |
||||
this.path = path; |
||||
} |
||||
|
||||
/** |
||||
* creates a sound track from the given resource path |
||||
* @param path the path to an audio file (ie : "Sounds/mySound.wav") |
||||
* @param initialDuration the initial duration of the event |
||||
* @param loopMode the loopMode |
||||
* @see LoopMode |
||||
*/ |
||||
public SoundEvent(String path, float initialDuration, LoopMode loopMode) { |
||||
super(initialDuration, loopMode); |
||||
this.path = path; |
||||
} |
||||
|
||||
/** |
||||
* creates a sound event |
||||
* used for serialization |
||||
*/ |
||||
public SoundEvent() { |
||||
super(); |
||||
} |
||||
|
||||
@Override |
||||
public void initEvent(Application app, Cinematic cinematic) { |
||||
super.initEvent(app, cinematic); |
||||
audioNode = new AudioNode(app.getAssetManager(), path, stream); |
||||
audioNode.setPositional(false); |
||||
setLoopMode(loopMode); |
||||
} |
||||
|
||||
@Override |
||||
public void setTime(float time) { |
||||
super.setTime(time); |
||||
//can occur on rewind
|
||||
if (time < 0f) { |
||||
stop(); |
||||
}else{ |
||||
audioNode.setTimeOffset(time); |
||||
} |
||||
} |
||||
|
||||
@Override |
||||
public void onPlay() { |
||||
audioNode.play(); |
||||
} |
||||
|
||||
@Override |
||||
public void onStop() { |
||||
audioNode.stop(); |
||||
|
||||
} |
||||
|
||||
@Override |
||||
public void onPause() { |
||||
audioNode.pause(); |
||||
} |
||||
|
||||
@Override |
||||
public void onUpdate(float tpf) { |
||||
if (audioNode.getStatus() == AudioSource.Status.Stopped) { |
||||
stop(); |
||||
} |
||||
} |
||||
|
||||
/** |
||||
* Returns the underlying audio node of this sound track |
||||
* @return |
||||
*/ |
||||
public AudioNode getAudioNode() { |
||||
return audioNode; |
||||
} |
||||
|
||||
@Override |
||||
public void setLoopMode(LoopMode loopMode) { |
||||
super.setLoopMode(loopMode); |
||||
|
||||
if (loopMode != LoopMode.DontLoop) { |
||||
audioNode.setLooping(true); |
||||
} else { |
||||
audioNode.setLooping(false); |
||||
} |
||||
} |
||||
|
||||
@Override |
||||
public void write(JmeExporter ex) throws IOException { |
||||
super.write(ex); |
||||
OutputCapsule oc = ex.getCapsule(this); |
||||
oc.write(path, "path", ""); |
||||
oc.write(stream, "stream", false); |
||||
} |
||||
|
||||
@Override |
||||
public void read(JmeImporter im) throws IOException { |
||||
super.read(im); |
||||
InputCapsule ic = im.getCapsule(this); |
||||
path = ic.readString("path", ""); |
||||
stream = ic.readBoolean("stream", false); |
||||
|
||||
} |
||||
} |
||||
|
@ -1,122 +1,123 @@ |
||||
/* |
||||
* Copyright (c) 2009-2012 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.scene; |
||||
|
||||
import com.jme3.export.JmeExporter; |
||||
import com.jme3.export.JmeImporter; |
||||
import com.jme3.renderer.Camera; |
||||
import com.jme3.scene.control.CameraControl; |
||||
import com.jme3.scene.control.CameraControl.ControlDirection; |
||||
import com.jme3.util.clone.Cloner; |
||||
import java.io.IOException; |
||||
|
||||
/** |
||||
* <code>CameraNode</code> simply uses {@link CameraControl} to implement |
||||
* linking of camera and node data. |
||||
* |
||||
* @author Tim8Dev |
||||
*/ |
||||
public class CameraNode extends Node { |
||||
|
||||
private CameraControl camControl; |
||||
|
||||
/** |
||||
* Serialization only. Do not use. |
||||
*/ |
||||
public CameraNode() { |
||||
} |
||||
|
||||
public CameraNode(String name, Camera camera) { |
||||
this(name, new CameraControl(camera)); |
||||
} |
||||
|
||||
public CameraNode(String name, CameraControl control) { |
||||
super(name); |
||||
addControl(control); |
||||
camControl = control; |
||||
} |
||||
|
||||
public void setEnabled(boolean enabled) { |
||||
camControl.setEnabled(enabled); |
||||
} |
||||
|
||||
public boolean isEnabled() { |
||||
return camControl.isEnabled(); |
||||
} |
||||
|
||||
public void setControlDir(ControlDirection controlDir) { |
||||
camControl.setControlDir(controlDir); |
||||
} |
||||
|
||||
public void setCamera(Camera camera) { |
||||
camControl.setCamera(camera); |
||||
} |
||||
|
||||
public ControlDirection getControlDir() { |
||||
return camControl.getControlDir(); |
||||
} |
||||
|
||||
public Camera getCamera() { |
||||
return camControl.getCamera(); |
||||
} |
||||
|
||||
// @Override
|
||||
// public void lookAt(Vector3f position, Vector3f upVector) {
|
||||
// this.lookAt(position, upVector);
|
||||
// camControl.getCamera().lookAt(position, upVector);
|
||||
// }
|
||||
|
||||
/** |
||||
* Called internally by com.jme3.util.clone.Cloner. Do not call directly. |
||||
*/ |
||||
@Override |
||||
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
|
||||
// to the wrong control. -pspeed
|
||||
this.camControl = cloner.clone(camControl); |
||||
} |
||||
|
||||
@Override |
||||
public void read(JmeImporter im) throws IOException { |
||||
super.read(im); |
||||
camControl = (CameraControl)im.getCapsule(this).readSavable("camControl", null); |
||||
} |
||||
|
||||
@Override |
||||
public void write(JmeExporter ex) throws IOException { |
||||
super.write(ex); |
||||
ex.getCapsule(this).write(camControl, "camControl", null); |
||||
} |
||||
} |
||||
/* |
||||
* Copyright (c) 2009-2012 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.scene; |
||||
|
||||
import com.jme3.export.JmeExporter; |
||||
import com.jme3.export.JmeImporter; |
||||
import com.jme3.renderer.Camera; |
||||
import com.jme3.scene.control.CameraControl; |
||||
import com.jme3.scene.control.CameraControl.ControlDirection; |
||||
import com.jme3.util.clone.Cloner; |
||||
import java.io.IOException; |
||||
|
||||
/** |
||||
* <code>CameraNode</code> simply uses {@link CameraControl} to implement |
||||
* linking of camera and node data. |
||||
* |
||||
* @author Tim8Dev |
||||
*/ |
||||
public class CameraNode extends Node { |
||||
|
||||
private CameraControl camControl; |
||||
|
||||
/** |
||||
* Serialization only. Do not use. |
||||
*/ |
||||
public CameraNode() { |
||||
super(); |
||||
} |
||||
|
||||
public CameraNode(String name, Camera camera) { |
||||
this(name, new CameraControl(camera)); |
||||
} |
||||
|
||||
public CameraNode(String name, CameraControl control) { |
||||
super(name); |
||||
addControl(control); |
||||
camControl = control; |
||||
} |
||||
|
||||
public void setEnabled(boolean enabled) { |
||||
camControl.setEnabled(enabled); |
||||
} |
||||
|
||||
public boolean isEnabled() { |
||||
return camControl.isEnabled(); |
||||
} |
||||
|
||||
public void setControlDir(ControlDirection controlDir) { |
||||
camControl.setControlDir(controlDir); |
||||
} |
||||
|
||||
public void setCamera(Camera camera) { |
||||
camControl.setCamera(camera); |
||||
} |
||||
|
||||
public ControlDirection getControlDir() { |
||||
return camControl.getControlDir(); |
||||
} |
||||
|
||||
public Camera getCamera() { |
||||
return camControl.getCamera(); |
||||
} |
||||
|
||||
// @Override
|
||||
// public void lookAt(Vector3f position, Vector3f upVector) {
|
||||
// this.lookAt(position, upVector);
|
||||
// camControl.getCamera().lookAt(position, upVector);
|
||||
// }
|
||||
|
||||
/** |
||||
* Called internally by com.jme3.util.clone.Cloner. Do not call directly. |
||||
*/ |
||||
@Override |
||||
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
|
||||
// to the wrong control. -pspeed
|
||||
this.camControl = cloner.clone(camControl); |
||||
} |
||||
|
||||
@Override |
||||
public void read(JmeImporter im) throws IOException { |
||||
super.read(im); |
||||
camControl = (CameraControl)im.getCapsule(this).readSavable("camControl", null); |
||||
} |
||||
|
||||
@Override |
||||
public void write(JmeExporter ex) throws IOException { |
||||
super.write(ex); |
||||
ex.getCapsule(this).write(camControl, "camControl", null); |
||||
} |
||||
} |
||||
|
Loading…
Reference in new issue