package com.pointcliki.core;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import org.newdawn.slick.GameContainer;
import org.newdawn.slick.Graphics;
import org.newdawn.slick.geom.Vector2f;
import com.pointcliki.event.Dispatcher;
import com.pointcliki.event.FrameManager;
import com.pointcliki.event.Minion;
import com.pointcliki.input.MouseEvent;
import com.pointcliki.input.InputManager.MouseEventDispatcher;
import com.pointcliki.ui.UIEntity;
/**
* A scene is the core display stage of a PointCliki game. Each stage keeps it's
* own time, game loop and scene graph.
*
* @author hugheth
* @since 2
* @see PointClikiGame IEntityGroup
*/
public class Scene extends UIEntity implements IManagerGroup {
/**
* Serial key
*/
private static final long serialVersionUID = -4722444989192283660L;
/**
* The game the scene belongs to
*/
protected PointClikiGame fGame;
protected Map<Class<? extends Manager>, Manager> fManagers = null;
transient protected TimeManager fTimeManager;
transient protected FrameManager fFrameManager;
transient protected EntityManager fEntityManager;
transient protected Minion<MouseEvent> fMouseMinion;
/**
* @param game The game of the scene
*/
public Scene(PointClikiGame game) {
fGame = game;
}
/**
* Initialise the scene. Use this method to create and add entities to the
* root
*/
public void init() {
// Configure the managers
configureManagers();
}
/**
* Configure the managers. Override this method to construct your own
* managers here.
*/
@Override
public void configureManagers() {
if (fManagers != null) return;
// Instantiate the managers map
fManagers = new HashMap<Class<? extends Manager>, Manager>();
fTimeManager = new TimeManager(this, 40);
fFrameManager = new FrameManager(this);
fManagers.put(TimeManager.class, fTimeManager);
fManagers.put(FrameManager.class, fFrameManager);
}
@Override
public List<Manager> managers() {
return new ArrayList<Manager>(fManagers.values());
}
@Override
public IManagerGroup parentManagerGroup() {
return fGame;
}
@SuppressWarnings("unchecked")
@Override
public <T> T manager(Class<T> type) {
if (!fManagers.containsKey(type)) parentManagerGroup().manager(type);
return (T) fManagers.get(type);
}
/**
* Get the game this scene belongs to
* @return The game containing the scene, or null if there is none
*/
public PointClikiGame game() {
return fGame;
}
/**
* Render the scene
*/
@Override
public void render(Graphics graphics, long currentTime) {
super.render(graphics, fTimeManager.currentTime());
}
/**
* Update the time manager
* @param c Game container
* @param delta Time delta
*/
public void update(GameContainer c, int delta) {
fTimeManager.update(c, delta);
}
@Override
public Scene scene() {
return this;
}
/**
* @return The parent scene of this scene, if the scene is included in the
* scene graph of another scene
*/
public Scene getParentScene() {
if (getParent() != null) return getParent().scene();
return null;
}
@Override
public void cleanup() {
super.cleanup();
for (Class<? extends Manager> cls: fManagers.keySet()) fManagers.get(cls).cleanup();
fManagers = null;
fTimeManager = null;
fFrameManager = null;
fEntityManager = null;
}
/**
* Restores the game state of scene from a snapshot of the scene
* @param from The previous snapshot of the scene
* @throws CloneNotSupportedException If a clone isn't supported
*/
public void restore(Scene from) throws CloneNotSupportedException {
// Iterate through saved managers
for (Class<? extends Manager> cls: from.fManagers.keySet()) {
Manager snapshot = from.fManagers.get(cls).snapshot();
// Restore each manager with the saved version
fManagers.get(cls).restore(snapshot);
}
// Restore the children
fChildren = from.fChildren;
// FIXME: Sort out entities
}
@Override
public ISavable snapshot() throws CloneNotSupportedException {
Scene clone = (Scene) super.snapshot();
clone.fManagers = new HashMap<Class<? extends Manager>, Manager>();
for (Class<? extends Manager> cls: fManagers.keySet()) {
Manager snapshot = fManagers.get(cls).snapshot();
clone.fManagers.put(cls, snapshot);
}
return clone;
}
protected void registerUIMinion() {
fMouseMinion = new Minion<MouseEvent>() {
@Override
public long run(Dispatcher<MouseEvent> dispatcher, String type, MouseEvent event) {
if (fDispatcher == null) return Minion.FINISH;
if (type.equals("mouse.down")) focus();
handleUIMouseEvent(type, new Vector2f(event.x(), event.y()), event);
return Minion.CONTINUE;
}
};
MouseEventDispatcher m = PointClikiGame.inputManager().mouseDispatcher();
m.addMinion("mouse.move", fMouseMinion);
m.addMinion("mouse.down", fMouseMinion);
m.addMinion("mouse.up", fMouseMinion);
m.addMinion("mouse.click", fMouseMinion);
m.addMinion("mouse.drag", fMouseMinion);
}
protected void unregisterUIMinion() {
if (fMouseMinion == null) return;
MouseEventDispatcher m = PointClikiGame.inputManager().mouseDispatcher();
m.removeMinion("mouse.move", fMouseMinion);
m.removeMinion("mouse.down", fMouseMinion);
m.removeMinion("mouse.up", fMouseMinion);
m.removeMinion("mouse.click", fMouseMinion);
m.removeMinion("mouse.drag", fMouseMinion);
fMouseMinion = null;
}
@Override
public String toString() {
String s = "[Scene";
for (Entity entity: this) s += " " + entity.toString();
s += "]";
return s;
}
/**
* Register an entity with the scene. This is performed automatically by an
* entity when entity.setScene() is called. This allows a scene snapshot to
* be taken saving the whole scene state which includes this entity.
*
* @param entity The entity to register to the scene
*/
public void register(Entity entity) {
// FIXME: Actually do a register
}
/**
* No longer track this entity with the scene
*
* @param entity The entity to unregister from the scene
*/
public void unregister(Entity entity) {
// FIXME: Actually do an unregister
}
}