package editor.model;
import beans.serializable.EventBloc;
import beans.core.GeneralConstant;
import beans.serializable.MapConfig;
import java.awt.AlphaComposite;
import java.awt.Color;
import java.awt.Dimension;
import java.awt.Graphics2D;
import java.awt.Image;
import java.awt.Point;
import java.awt.image.BufferedImage;
import java.io.File;
import java.io.IOException;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.Observable;
import javax.imageio.ImageIO;
import editor.core.PopUpGenerator;
import editor.screen.ListTileSetScreen;
import editor.screen.MapPanel;
import java.util.HashMap;
import java.util.Map.Entry;
/**
* Cette classe permet de gerer la creation d'une map
* @author mastersnes
*/
public class EditorModel extends Observable {
private List<BufferedImage> tilesetList;
private MapConfig config;
private GUIModel guiModel;
private int currentLayer;
private Image currentBloc;
private BufferedImage grille;
private String background;
private final Map<Integer, BufferedImage> layers;
private void init(final int width, final int height) {
initTileSetList();
currentLayer = 1;
currentBloc = tilesetList.get(0).getSubimage(0, 0, GeneralConstant.BLOC_WIDTH, GeneralConstant.BLOC_HEIGHT);
guiModel.setLeftPanel(new MapPanel(this), new Dimension(width * GeneralConstant.BLOC_WIDTH, height * GeneralConstant.BLOC_HEIGHT));
guiModel.setRightPanel(new ListTileSetScreen(this));
if (config == null) {
config = new MapConfig();
}
config.setBackground(background);
Graphics2D g = createGrid(width, height);
g.dispose();
}
private void initTileSetList() {
tilesetList = new ArrayList<BufferedImage>();
final File f = new File(GeneralConstant.TILESET_PATH);
for (final File file : f.listFiles()) {
try {
final BufferedImage currentImage = ImageIO.read(file);
if (currentImage != null) {
tilesetList.add(currentImage);
}
} catch (final IOException ex) {
}
}
}
private Graphics2D createGrid(final int width, final int height) {
grille = new BufferedImage(width * GeneralConstant.BLOC_WIDTH, height * GeneralConstant.BLOC_HEIGHT, BufferedImage.TYPE_INT_ARGB);
Graphics2D g = grille.createGraphics();
g.setColor(Color.WHITE);
for (int i = 0; i < grille.getWidth(); i += GeneralConstant.BLOC_WIDTH) {
g.drawLine(i, 0, i, grille.getHeight());
}
for (int j = 0; j < grille.getHeight(); j += GeneralConstant.BLOC_HEIGHT) {
g.drawLine(0, j, grille.getWidth(), j);
}
return g;
}
/**
* Le constructeur qui est appelé quand vous créez une nouvelle map
* The constucteur wich is called when you create a new map
* @param fields
* @param guiModel
* @see GUIModel
*/
public EditorModel(final Map<String, String> fields, final GUIModel guiModel) {
this.guiModel = guiModel;
layers = new HashMap<Integer, BufferedImage>();
final int width = Integer.parseInt(fields.get("width"));
final int height = Integer.parseInt(fields.get("height"));
background = fields.get("background");
for (int i = 1; i < 5; i++) {
final BufferedImage image = new BufferedImage(width * GeneralConstant.BLOC_WIDTH, height * GeneralConstant.BLOC_HEIGHT, BufferedImage.TYPE_INT_ARGB);
layers.put(i, image);
}
init(width, height);
}
/**
* Le constructeur qui est appelé quand vous chargez une map existante
* The constucteur wich is called when you load an existing map
* @param layer
* @param config
* @param guiModel
* @see GUIModel
* @see MapConfig
*/
public EditorModel(final Map<Integer, BufferedImage> layer, final MapConfig config, final GUIModel guiModel) {
this.guiModel = guiModel;
this.layers = layer;
this.config = config;
final BufferedImage notNull = findNotNull(layers);
final int width = notNull.getWidth() / GeneralConstant.BLOC_WIDTH;
final int height = notNull.getHeight() / GeneralConstant.BLOC_HEIGHT;
init(width, height);
}
/**
* Ajoute le bloc courant sur la couche courante à la position blocPosition
* @param blocPosition
*/
public void addBlock(final Point blocPosition) {
if (currentLayer == GeneralConstant.EVENT_NUM) {
addEvent(blocPosition);
} else {
final BufferedImage currentPlan = layers.get(currentLayer);
final Graphics2D g = currentPlan.createGraphics();
g.setColor(Color.red);
g.drawImage(currentBloc, blocPosition.x * GeneralConstant.BLOC_WIDTH, blocPosition.y * GeneralConstant.BLOC_HEIGHT, GeneralConstant.BLOC_WIDTH, GeneralConstant.BLOC_HEIGHT, null);
g.dispose();
setChanged();
notifyObservers();
}
}
/**
* retourne l'image de la couche courante
* @return la couche courante
*/
public Image getMap() {
return layers.get(currentLayer);
}
/**
* retourne la liste des differents tileSets
* @return liste des differents tileSet
*/
public List<BufferedImage> getTilesetList() {
return tilesetList;
}
/**
* Retrouve le bloc situé à la position point dans la liste des tileSets
* @param point
*/
public void findCurrentBlock(final Point point) {
if (currentLayer == GeneralConstant.COLISION_NUM) {
if (point.y == 0) {
final BufferedImage interestedImage = new BufferedImage(GeneralConstant.BLOC_WIDTH, GeneralConstant.BLOC_HEIGHT, BufferedImage.TYPE_INT_ARGB);
final Graphics2D g = interestedImage.createGraphics();
if (point.x == 0) {
g.setColor(Color.BLACK);
g.fillRect(0, 0, GeneralConstant.BLOC_WIDTH, GeneralConstant.BLOC_HEIGHT);
g.dispose();
currentBloc = interestedImage;
return;
}
}
} else {
if (point.y < tilesetList.size()) {
BufferedImage interestedImage = tilesetList.get(point.y);
if (point.x * GeneralConstant.BLOC_WIDTH < interestedImage.getWidth()) {
currentBloc = interestedImage.getSubimage(point.x * GeneralConstant.BLOC_WIDTH, 0, GeneralConstant.BLOC_WIDTH, GeneralConstant.BLOC_HEIGHT);
}
}
}
}
/**
* Retourne les differentes couches
* @return les couches
*/
public Map<Integer, BufferedImage> getLayers() {
return layers;
}
/**
* Selectionne la nouvelle couche comme couche courante<br>
* Le curseur est remis à 0 pour eviter tout problemes<br>
* Ainsi le bloc courant sera le premier bloc de la liste
* @param layer
*/
public void setLayer(final int layer) {
currentLayer = layer;
findCurrentBlock(new Point(0, 0));
setChanged();
notifyObservers();
}
/**
* Retourne le numero de la couche courante
* @return le numero de la couche courante
*/
public int getCurrentLayer() {
return currentLayer;
}
private BufferedImage findNotNull(final Map<Integer, BufferedImage> couches) {
for (int i = 1; i < 5; i++) {
if (couches.get(i) != null) {
return couches.get(i);
}
}
return new BufferedImage(1, 1, BufferedImage.TYPE_INT_ARGB);
}
private void addEvent(final Point blocPosition) {
if (getConfig().getEvent().containsKey(blocPosition)) {
PopUpGenerator.showInitEventPopUp(this, blocPosition, getConfig().getEvent().get(blocPosition));
} else {
PopUpGenerator.showInitEventPopUp(this, blocPosition);
}
}
/**
* Methode appellé pour gerer la reponse d'une popUp de creation d'un evenement
* @param event
* @param position
*/
public void addEventResponse(final Point position, final EventBloc event) {
config.getEvent().put(position, event);
setChanged();
notifyObservers();
}
/**
* Retourne la configuration de la map
* @return La configuration
* @see MapConfig
*/
public MapConfig getConfig() {
return config;
}
/**
* Retourne la grille associé à la couche d'evenement
* @return L'image de la grille
*/
public BufferedImage getGrille() {
return grille;
}
/**
* Efface le bloc de la couche courante se trouvant à la position blocPosition
* @param blocPosition
*/
public void eraseBlock(final Point blocPosition) {
if (currentLayer == GeneralConstant.EVENT_NUM) {
eraseEvent(blocPosition);
} else {
final BufferedImage currentPlan = layers.get(currentLayer);
final Graphics2D g = currentPlan.createGraphics();
g.setComposite(AlphaComposite.Clear);
g.setColor(Color.red);
g.fillRect(blocPosition.x * GeneralConstant.BLOC_WIDTH, blocPosition.y * GeneralConstant.BLOC_HEIGHT, GeneralConstant.BLOC_WIDTH, GeneralConstant.BLOC_HEIGHT);
g.dispose();
}
setChanged();
notifyObservers();
}
private void eraseEvent(final Point blocPosition) {
config.getEvent().remove(blocPosition);
setChanged();
notifyObservers();
}
/**
* Permet de redimensionner la map
* @param width
* @param height
*/
public void redimensionner(final int width, final int height) {
for (final Entry<Integer, BufferedImage> entry : layers.entrySet()) {
final BufferedImage imageFinal = new BufferedImage(width * GeneralConstant.BLOC_WIDTH, height * GeneralConstant.BLOC_HEIGHT, BufferedImage.TYPE_INT_ARGB);
final Graphics2D g = imageFinal.createGraphics();
g.drawImage(entry.getValue(), 0, 0, null);
g.dispose();
layers.put(entry.getKey(), imageFinal);
}
createGrid(width, height);
setChanged();
notifyObservers();
}
}