159b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta/* 259b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta * Copyright (c) 2009-2010 jMonkeyEngine 359b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta * All rights reserved. 459b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta * 559b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta * Redistribution and use in source and binary forms, with or without 659b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta * modification, are permitted provided that the following conditions are 759b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta * met: 859b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta * 959b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta * * Redistributions of source code must retain the above copyright 1059b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta * notice, this list of conditions and the following disclaimer. 1159b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta * 1259b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta * * Redistributions in binary form must reproduce the above copyright 1359b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta * notice, this list of conditions and the following disclaimer in the 1459b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta * documentation and/or other materials provided with the distribution. 1559b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta * 1659b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta * * Neither the name of 'jMonkeyEngine' nor the names of its contributors 1759b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta * may be used to endorse or promote products derived from this software 1859b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta * without specific prior written permission. 1959b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta * 2059b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 2159b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED 2259b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 2359b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR 2459b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, 2559b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, 2659b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR 2759b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF 2859b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING 2959b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS 3059b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 3159b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta */ 3259b2e6871c65f58fdad78cd7229c292f6a177578Scott Bartapackage com.jme3.animation; 3359b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta 3459b2e6871c65f58fdad78cd7229c292f6a177578Scott Bartaimport com.jme3.export.*; 3559b2e6871c65f58fdad78cd7229c292f6a177578Scott Bartaimport com.jme3.renderer.RenderManager; 3659b2e6871c65f58fdad78cd7229c292f6a177578Scott Bartaimport com.jme3.renderer.ViewPort; 3759b2e6871c65f58fdad78cd7229c292f6a177578Scott Bartaimport com.jme3.scene.Mesh; 3859b2e6871c65f58fdad78cd7229c292f6a177578Scott Bartaimport com.jme3.scene.Spatial; 3959b2e6871c65f58fdad78cd7229c292f6a177578Scott Bartaimport com.jme3.scene.control.AbstractControl; 4059b2e6871c65f58fdad78cd7229c292f6a177578Scott Bartaimport com.jme3.scene.control.Control; 4159b2e6871c65f58fdad78cd7229c292f6a177578Scott Bartaimport com.jme3.util.TempVars; 4259b2e6871c65f58fdad78cd7229c292f6a177578Scott Bartaimport java.io.IOException; 4359b2e6871c65f58fdad78cd7229c292f6a177578Scott Bartaimport java.util.ArrayList; 4459b2e6871c65f58fdad78cd7229c292f6a177578Scott Bartaimport java.util.Collection; 4559b2e6871c65f58fdad78cd7229c292f6a177578Scott Bartaimport java.util.HashMap; 4659b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta 4759b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta/** 4859b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta * <code>AnimControl</code> is a Spatial control that allows manipulation 4959b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta * of skeletal animation. 5059b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta * 5159b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta * The control currently supports: 5259b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta * 1) Animation blending/transitions 5359b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta * 2) Multiple animation channels 5459b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta * 3) Multiple skins 5559b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta * 4) Animation event listeners 5659b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta * 5) Animated model cloning 5759b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta * 6) Animated model binary import/export 5859b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta * 5959b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta * Planned: 6059b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta * 1) Hardware skinning 6159b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta * 2) Morph/Pose animation 6259b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta * 3) Attachments 6359b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta * 4) Add/remove skins 6459b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta * 6559b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta * @author Kirill Vainer 6659b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta */ 6759b2e6871c65f58fdad78cd7229c292f6a177578Scott Bartapublic final class AnimControl extends AbstractControl implements Cloneable { 6859b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta 6959b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta /** 7059b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta * Skeleton object must contain corresponding data for the targets' weight buffers. 7159b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta */ 7259b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta Skeleton skeleton; 7359b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta /** only used for backward compatibility */ 7459b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta @Deprecated 7559b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta private SkeletonControl skeletonControl; 7659b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta /** 7759b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta * List of animations 7859b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta */ 7959b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta HashMap<String, Animation> animationMap; 8059b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta /** 8159b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta * Animation channels 8259b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta */ 8359b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta private transient ArrayList<AnimChannel> channels = new ArrayList<AnimChannel>(); 8459b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta /** 8559b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta * Animation event listeners 8659b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta */ 8759b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta private transient ArrayList<AnimEventListener> listeners = new ArrayList<AnimEventListener>(); 8859b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta 8959b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta /** 9059b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta * Creates a new animation control for the given skeleton. 9159b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta * The method {@link AnimControl#setAnimations(java.util.HashMap) } 9259b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta * must be called after initialization in order for this class to be useful. 9359b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta * 9459b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta * @param skeleton The skeleton to animate 9559b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta */ 9659b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta public AnimControl(Skeleton skeleton) { 9759b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta this.skeleton = skeleton; 9859b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta reset(); 9959b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta } 10059b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta 10159b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta /** 10259b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta * Serialization only. Do not use. 10359b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta */ 10459b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta public AnimControl() { 10559b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta } 10659b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta 10759b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta /** 10859b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta * Internal use only. 10959b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta */ 11059b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta public Control cloneForSpatial(Spatial spatial) { 11159b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta try { 11259b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta AnimControl clone = (AnimControl) super.clone(); 11359b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta clone.spatial = spatial; 11459b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta clone.channels = new ArrayList<AnimChannel>(); 11559b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta clone.listeners = new ArrayList<AnimEventListener>(); 11659b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta 11759b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta if (skeleton != null) { 11859b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta clone.skeleton = new Skeleton(skeleton); 11959b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta } 12059b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta 12159b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta // animationMap is reference-copied, animation data should be shared 12259b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta // to reduce memory usage. 12359b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta 12459b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta return clone; 12559b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta } catch (CloneNotSupportedException ex) { 12659b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta throw new AssertionError(); 12759b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta } 12859b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta } 12959b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta 13059b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta /** 13159b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta * @param animations Set the animations that this <code>AnimControl</code> 13259b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta * will be capable of playing. The animations should be compatible 13359b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta * with the skeleton given in the constructor. 13459b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta */ 13559b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta public void setAnimations(HashMap<String, Animation> animations) { 13659b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta animationMap = animations; 13759b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta } 13859b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta 13959b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta /** 14059b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta * Retrieve an animation from the list of animations. 14159b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta * @param name The name of the animation to retrieve. 14259b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta * @return The animation corresponding to the given name, or null, if no 14359b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta * such named animation exists. 14459b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta */ 14559b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta public Animation getAnim(String name) { 14659b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta if (animationMap == null) { 14759b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta animationMap = new HashMap<String, Animation>(); 14859b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta } 14959b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta return animationMap.get(name); 15059b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta } 15159b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta 15259b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta /** 15359b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta * Adds an animation to be available for playing to this 15459b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta * <code>AnimControl</code>. 15559b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta * @param anim The animation to add. 15659b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta */ 15759b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta public void addAnim(Animation anim) { 15859b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta if (animationMap == null) { 15959b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta animationMap = new HashMap<String, Animation>(); 16059b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta } 16159b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta animationMap.put(anim.getName(), anim); 16259b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta } 16359b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta 16459b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta /** 16559b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta * Remove an animation so that it is no longer available for playing. 16659b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta * @param anim The animation to remove. 16759b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta */ 16859b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta public void removeAnim(Animation anim) { 16959b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta if (!animationMap.containsKey(anim.getName())) { 17059b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta throw new IllegalArgumentException("Given animation does not exist " 17159b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta + "in this AnimControl"); 17259b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta } 17359b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta 17459b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta animationMap.remove(anim.getName()); 17559b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta } 17659b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta 17759b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta /** 17859b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta * Create a new animation channel, by default assigned to all bones 17959b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta * in the skeleton. 18059b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta * 18159b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta * @return A new animation channel for this <code>AnimControl</code>. 18259b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta */ 18359b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta public AnimChannel createChannel() { 18459b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta AnimChannel channel = new AnimChannel(this); 18559b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta channels.add(channel); 18659b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta return channel; 18759b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta } 18859b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta 18959b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta /** 19059b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta * Return the animation channel at the given index. 19159b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta * @param index The index, starting at 0, to retrieve the <code>AnimChannel</code>. 19259b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta * @return The animation channel at the given index, or throws an exception 19359b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta * if the index is out of bounds. 19459b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta * 19559b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta * @throws IndexOutOfBoundsException If no channel exists at the given index. 19659b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta */ 19759b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta public AnimChannel getChannel(int index) { 19859b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta return channels.get(index); 19959b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta } 20059b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta 20159b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta /** 20259b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta * @return The number of channels that are controlled by this 20359b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta * <code>AnimControl</code>. 20459b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta * 20559b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta * @see AnimControl#createChannel() 20659b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta */ 20759b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta public int getNumChannels() { 20859b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta return channels.size(); 20959b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta } 21059b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta 21159b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta /** 21259b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta * Clears all the channels that were created. 21359b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta * 21459b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta * @see AnimControl#createChannel() 21559b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta */ 21659b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta public void clearChannels() { 21759b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta channels.clear(); 21859b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta } 21959b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta 22059b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta /** 22159b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta * @return The skeleton of this <code>AnimControl</code>. 22259b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta */ 22359b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta public Skeleton getSkeleton() { 22459b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta return skeleton; 22559b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta } 22659b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta 22759b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta /** 22859b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta * Adds a new listener to receive animation related events. 22959b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta * @param listener The listener to add. 23059b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta */ 23159b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta public void addListener(AnimEventListener listener) { 23259b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta if (listeners.contains(listener)) { 23359b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta throw new IllegalArgumentException("The given listener is already " 23459b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta + "registed at this AnimControl"); 23559b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta } 23659b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta 23759b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta listeners.add(listener); 23859b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta } 23959b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta 24059b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta /** 24159b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta * Removes the given listener from listening to events. 24259b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta * @param listener 24359b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta * @see AnimControl#addListener(com.jme3.animation.AnimEventListener) 24459b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta */ 24559b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta public void removeListener(AnimEventListener listener) { 24659b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta if (!listeners.remove(listener)) { 24759b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta throw new IllegalArgumentException("The given listener is not " 24859b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta + "registed at this AnimControl"); 24959b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta } 25059b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta } 25159b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta 25259b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta /** 25359b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta * Clears all the listeners added to this <code>AnimControl</code> 25459b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta * 25559b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta * @see AnimControl#addListener(com.jme3.animation.AnimEventListener) 25659b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta */ 25759b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta public void clearListeners() { 25859b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta listeners.clear(); 25959b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta } 26059b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta 26159b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta void notifyAnimChange(AnimChannel channel, String name) { 26259b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta for (int i = 0; i < listeners.size(); i++) { 26359b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta listeners.get(i).onAnimChange(this, channel, name); 26459b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta } 26559b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta } 26659b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta 26759b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta void notifyAnimCycleDone(AnimChannel channel, String name) { 26859b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta for (int i = 0; i < listeners.size(); i++) { 26959b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta listeners.get(i).onAnimCycleDone(this, channel, name); 27059b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta } 27159b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta } 27259b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta 27359b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta /** 27459b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta * Internal use only. 27559b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta */ 27659b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta @Override 27759b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta public void setSpatial(Spatial spatial) { 27859b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta if (spatial == null && skeletonControl != null) { 27959b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta this.spatial.removeControl(skeletonControl); 28059b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta } 28159b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta 28259b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta super.setSpatial(spatial); 28359b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta 28459b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta //Backward compatibility. 28559b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta if (spatial != null && skeletonControl != null) { 28659b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta spatial.addControl(skeletonControl); 28759b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta } 28859b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta } 28959b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta 29059b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta final void reset() { 29159b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta if (skeleton != null) { 29259b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta skeleton.resetAndUpdate(); 29359b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta } 29459b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta } 29559b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta 29659b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta /** 29759b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta * @return The names of all animations that this <code>AnimControl</code> 29859b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta * can play. 29959b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta */ 30059b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta public Collection<String> getAnimationNames() { 30159b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta return animationMap.keySet(); 30259b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta } 30359b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta 30459b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta /** 30559b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta * Returns the length of the given named animation. 30659b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta * @param name The name of the animation 30759b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta * @return The length of time, in seconds, of the named animation. 30859b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta */ 30959b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta public float getAnimationLength(String name) { 31059b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta Animation a = animationMap.get(name); 31159b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta if (a == null) { 31259b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta throw new IllegalArgumentException("The animation " + name 31359b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta + " does not exist in this AnimControl"); 31459b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta } 31559b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta 31659b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta return a.getLength(); 31759b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta } 31859b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta 31959b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta /** 32059b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta * Internal use only. 32159b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta */ 32259b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta @Override 32359b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta protected void controlUpdate(float tpf) { 32459b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta if (skeleton != null) { 32559b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta skeleton.reset(); // reset skeleton to bind pose 32659b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta } 32759b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta 32859b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta TempVars vars = TempVars.get(); 32959b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta for (int i = 0; i < channels.size(); i++) { 33059b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta channels.get(i).update(tpf, vars); 33159b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta } 33259b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta vars.release(); 33359b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta 33459b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta if (skeleton != null) { 33559b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta skeleton.updateWorldVectors(); 33659b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta } 33759b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta } 33859b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta 33959b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta /** 34059b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta * Internal use only. 34159b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta */ 34259b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta @Override 34359b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta protected void controlRender(RenderManager rm, ViewPort vp) { 34459b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta } 34559b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta 34659b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta @Override 34759b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta public void write(JmeExporter ex) throws IOException { 34859b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta super.write(ex); 34959b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta OutputCapsule oc = ex.getCapsule(this); 35059b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta oc.write(skeleton, "skeleton", null); 35159b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta oc.writeStringSavableMap(animationMap, "animations", null); 35259b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta } 35359b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta 35459b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta @Override 35559b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta public void read(JmeImporter im) throws IOException { 35659b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta super.read(im); 35759b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta InputCapsule in = im.getCapsule(this); 35859b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta skeleton = (Skeleton) in.readSavable("skeleton", null); 35959b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta animationMap = (HashMap<String, Animation>) in.readStringSavableMap("animations", null); 36059b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta 36159b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta if (im.getFormatVersion() == 0) { 36259b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta // Changed for backward compatibility with j3o files generated 36359b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta // before the AnimControl/SkeletonControl split. 36459b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta 36559b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta // If we find a target mesh array the AnimControl creates the 36659b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta // SkeletonControl for old files and add it to the spatial. 36759b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta // When backward compatibility won't be needed anymore this can deleted 36859b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta Savable[] sav = in.readSavableArray("targets", null); 36959b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta if (sav != null) { 37059b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta Mesh[] targets = new Mesh[sav.length]; 37159b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta System.arraycopy(sav, 0, targets, 0, sav.length); 37259b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta skeletonControl = new SkeletonControl(targets, skeleton); 37359b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta spatial.addControl(skeletonControl); 37459b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta } 37559b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta } 37659b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta } 37759b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta} 378