package org.multiverseking.render.animation; import org.multiverseking.core.utility.SubSystem; import com.jme3.animation.AnimChannel; import com.jme3.animation.AnimControl; import com.jme3.animation.AnimEventListener; import com.jme3.animation.LoopMode; import com.simsilica.es.Entity; import com.simsilica.es.EntityId; import com.simsilica.es.EntitySet; import org.multiverseking.core.utility.EntitySystemAppState; import java.util.HashMap; import java.util.logging.Level; import java.util.logging.Logger; import org.multiverseking.render.RenderComponent; import org.multiverseking.render.RenderSystem; import org.multiverseking.utility.Utility; /** * Handle how animation work when they got they cycle done or under defined * pattern. * * @todo make this a sub-system of the renderSystem * * @author roah */ public class AnimationSystem extends EntitySystemAppState implements AnimEventListener, SubSystem { private RenderSystem renderSystem; private HashMap<EntityId, AnimControl> animControls = new HashMap<>(); @Override protected EntitySet initialiseSystem() { renderSystem = app.getStateManager().getState(RenderSystem.class); renderSystem.registerSubSystem(this); return entityData.getEntities(AnimationComponent.class, RenderComponent.class); } @Override protected void updateSystem(float tpf) { // Use onAnimCycleDone && onAnimChange } @Override protected void addEntity(Entity e) { AnimControl control = renderSystem.getControl(e.getId(), AnimControl.class); if (control == null) { entityData.removeComponent(e.getId(), AnimationComponent.class); Logger.getGlobal().log(Level.WARNING, "{0} : There is no Animation control for : {1}.", new Object[]{getClass().getName(), e.get(RenderComponent.class).getName()}); return; } control.addListener(this); AnimChannel channel = control.createChannel(); setPlay(channel, e.get(AnimationComponent.class).getAnimation()); animControls.put(e.getId(), control); } @Override protected void updateEntity(Entity e) { if (renderSystem.getControl(e.getId(), AnimControl.class) != animControls.get(e.getId())) { removeEntity(e); addEntity(e); return; } Animation toPlay = e.get(AnimationComponent.class).getAnimation(); if (!animControls.get(e.getId()).getChannel(0).getAnimationName().equals(toPlay.toString())) { setPlay(animControls.get(e.getId()).getChannel(0), toPlay); } // if(e.get(TimeBreakComponent.class).isTimeBreak()){ // animControls.get(e.getId()).getChannel(0).setSpeed(0); // } else if(!e.get(TimeBreakComponent.class).isTimeBreak() && animControls.get(e.getId()).getChannel(0).getSpeed() == 0f) { // animControls.get(e.getId()).getChannel(0).setSpeed(1f); // } } @Override protected void removeEntity(Entity e) { AnimControl animControl = animControls.get(e.getId()); if (animControl == null) { return; } animControl.clearChannels(); animControl.clearListeners(); animControls.remove(e.getId()); } @Override protected void cleanupSystem() { for (AnimControl control : animControls.values()) { control.clearChannels(); control.clearListeners(); } animControls.clear(); } /** * Activate the defined animation in the AnimationComponent, on the main * channel (Currently only one channel is used). * * @param channel to use for the animation. * @param anim animation to play. */ private void setPlay(AnimChannel channel, Animation anim) { if (channel.getControl().getAnimationNames().contains(anim.name())) { switch (anim) { case IDLE: channel.setAnim(anim.toString(), 0.50f); channel.setLoopMode(LoopMode.Loop); channel.setSpeed(1f); break; case SUMMON: channel.setAnim(anim.toString()); channel.setLoopMode(LoopMode.DontLoop); break; case WALK: channel.setAnim(anim.toString(), 0.50f); channel.setLoopMode(LoopMode.Loop); break; default: System.err.println(anim.name() + " Is not a supported animation type."); } } else if (anim.equals(Animation.SUMMON)) { setPlay(channel, Animation.IDLE); } } /** * Called When an animation on a channel ended his life cycle. * * @param control who this animation belong. * @param channel channel used by the animation. * @param animName name of the ended animation. */ @Override public void onAnimCycleDone(AnimControl control, AnimChannel channel, String animName) { if (animName.equals(Animation.SUMMON.toString())) { EntityId id = Utility.getKeyByValue(animControls, control); entityData.setComponent(id, new AnimationComponent(Animation.IDLE)); } } /** * Called when an animation got changed during his life cycle. * * @param control who this animation belong. * @param channel channel used by the animation. * @param animName name of the ended animation. * @deprecated not used on the current context. */ @Override public void onAnimChange(AnimControl control, AnimChannel channel, String animName) { // throw new UnsupportedOperationException("Not supported yet."); //To change body of generated methods, choose Tools | Templates. } @Override public void rootSystemIsRemoved() { app.getStateManager().detach(this); } }