package org.codecranachan.asteroidpush.base.workshop.actor;
import java.util.Collection;
import java.util.HashMap;
import java.util.HashSet;
import java.util.LinkedList;
import java.util.Map;
import java.util.Set;
import org.codecranachan.asteroidpush.base.input.Controllable;
import org.codecranachan.asteroidpush.base.input.Controller;
import org.codecranachan.asteroidpush.base.simulation.RigidBody;
import org.codecranachan.asteroidpush.base.simulation.RigidBodyFactory;
import org.codecranachan.asteroidpush.base.simulation.command.Command;
import org.codecranachan.asteroidpush.base.visuals.Representation;
import org.codecranachan.asteroidpush.utils.NewtonianState;
import org.codecranachan.asteroidpush.utils.OrthogonalCoordinate;
public class ActorSkeleton implements Controllable {
private BodyGraph graph;
private Map<OrthogonalCoordinate, BodyVertex> mesh;
private BodyAssociationManager bodyManager;
public ActorSkeleton() {
graph = new BodyGraph();
mesh = new HashMap<OrthogonalCoordinate, BodyVertex>();
bodyManager = new BodyAssociationManager(graph);
graph.addGraphListener(bodyManager);
}
/**
* Delegates the update callback to all behaviors attached to the skeleton.
*
* Warning: This will only trigger behaviors that have bodies plugged on
* index 0. At the time, this seemed the easiest way to prevent behaviors
* getting updated twice in a single frame.
*
* @param frame
* The current simulation frame number
*/
public Collection<Command> update(int frame) {
Collection<Command> commands = new LinkedList<Command>();
for (BodyVertex vertex : graph.vertexSet()) {
for (Plug plug : vertex.getPlugs()) {
if (plug.getIndex() == 0) {
commands.addAll(plug.getBehavior().update(frame));
}
}
}
return commands;
}
/**
* Retrieves the representations of all behaviors attached to the skeleton.
*
* @return A collection of representations
*/
public Collection<Representation> getRepresentations() {
Collection<Representation> representations = new LinkedList<Representation>();
for (BodyVertex vertex : graph.vertexSet()) {
for (Plug plug : vertex.getPlugs()) {
if (plug.getIndex() == 0) {
representations.addAll(plug.getBehavior().getRepresentations());
}
}
}
return representations;
}
public void insertVertex(BodyVertex addedVertex,
Collection<OrthogonalCoordinate> links) {
assert addedVertex != null;
assert links != null;
graph.addVertex(addedVertex);
for (OrthogonalCoordinate item : links) {
BodyVertex linkVertex;
if (mesh.containsKey(item)) {
linkVertex = mesh.get(item);
} else {
linkVertex = new BodyVertex();
mesh.put(item, linkVertex);
graph.addVertex(linkVertex);
}
graph.addEdge(addedVertex, linkVertex);
}
}
public void spawnBodies(NewtonianState initialState, RigidBodyFactory factory) {
bodyManager.spawnMissingBodies(initialState, factory);
}
public Set<RigidBody> getBodies() {
Set<RigidBody> bodies = new HashSet<RigidBody>();
for (BodyVertex vertex : graph.vertexSet()) {
bodies.add(vertex.getBody());
}
return bodies;
}
public void setController(Controller controller) {
for (BodyVertex vertex : graph.vertexSet()) {
for (Plug plug : vertex.getPlugs()) {
plug.getBehavior().setController(controller, plug.getIndex());
}
}
}
public void explode() {
for (BodyVertex link : mesh.values()) {
graph.removeVertex(link);
}
}
}