package rescuecore2.standard.view; import java.util.Map; import java.util.Set; import java.util.HashSet; import java.util.HashMap; import java.util.Queue; import java.util.LinkedList; import rescuecore2.misc.Pair; import rescuecore2.config.Config; import rescuecore2.worldmodel.EntityID; import rescuecore2.standard.entities.Human; import rescuecore2.standard.misc.AgentPath; /** A view layer that animates human movements. */ public class AnimatedHumanLayer extends HumanLayer { private Set<EntityID> humanIDs; private Map<EntityID, Queue<Pair<Integer, Integer>>> frames; private boolean animationDone; /** Construct an animated human view layer. */ public AnimatedHumanLayer() { humanIDs = new HashSet<EntityID>(); frames = new HashMap<EntityID, Queue<Pair<Integer, Integer>>>(); animationDone = true; } @Override public void initialise(Config config) { super.initialise(config); humanIDs.clear(); synchronized (this) { frames.clear(); animationDone = true; } } @Override public String getName() { return "Humans (animated)"; } /** Increase the frame number. @return True if a new frame is actually required. */ public boolean nextFrame() { synchronized (this) { if (animationDone) { return false; } animationDone = true; for (Queue<Pair<Integer, Integer>> next : frames.values()) { if (next.size() > 1) { next.remove(); animationDone = false; } } return !animationDone; } } @Override protected Pair<Integer, Integer> getLocation(Human h) { synchronized (this) { Queue<Pair<Integer, Integer>> agentFrames = frames.get(h.getID()); if (agentFrames != null && !agentFrames.isEmpty()) { return agentFrames.peek(); } } return h.getLocation(world); } @Override protected void preView() { super.preView(); humanIDs.clear(); } @Override protected void viewObject(Object o) { super.viewObject(o); if (o instanceof Human) { humanIDs.add(((Human)o).getID()); } } /** Compute the animation frames. @param frameCount The number of animation frames to compute. */ void computeAnimation(int frameCount) { synchronized (this) { frames.clear(); // Compute animation double step = 1.0 / (frameCount - 1.0); for (EntityID next : humanIDs) { Queue<Pair<Integer, Integer>> result = new LinkedList<Pair<Integer, Integer>>(); Human human = (Human)world.getEntity(next); if (human == null) { continue; } AgentPath path = AgentPath.computePath(human, world); if (path == null) { continue; } for (int i = 0; i < frameCount; ++i) { Pair<Integer, Integer> nextPoint = path.getPointOnPath(i * step); result.add(nextPoint); } frames.put(next, result); } animationDone = false; } } }