package vooga.rts.leveleditor.gui;
import java.awt.BasicStroke;
import java.awt.Color;
import java.awt.Dimension;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.Point;
import java.awt.geom.Point2D;
import java.awt.image.BufferedImage;
import javax.swing.JComponent;
import util.Location;
import util.input.Input;
import util.input.InputClassTarget;
import util.input.InputMethodTarget;
import util.input.PositionObject;
import vooga.rts.leveleditor.components.EditableMap;
import vooga.rts.leveleditor.components.EditableTerrain;
import vooga.rts.leveleditor.components.EditableTile;
import vooga.rts.leveleditor.components.EditableResource;
import vooga.rts.resourcemanager.ResourceManager;
import vooga.rts.util.Camera;
import vooga.rts.util.Location3D;
/**
* This panel is responsible for displaying the
* map editted by the user, every map component
* will be painted on this panel
*
* @author Ziqiang Huang
*
*/
@SuppressWarnings("serial")
@InputClassTarget
public class MapPanel extends JComponent {
public static final String INPUT_DIR = "vooga.rts.resources.properties.Input";
public static final String PLAYER_IMAGE_PATH = "Player1.png";
public static final Dimension DEFAULT_MAP_SIZE = new Dimension(600, 600);
public static final int RESOURCEMODE = 1;
public static final int PLAYERMODE = 2;
public static final int TERRAINMODE = 3;
public static final int TILEMODE = 4;
public static final int FILLMODE = 5;
public static final int REMOVEMODE = 6;
private Canvas myCanvas;
private EditableMap myMap;
private Input myInput;
private int myWidth;
private int myHeight;
private int myTileWidth;
private int myTileHeight;
private int myCurrentLayer;
private int myMaxLayer;
private int myMode;
private BufferedImage myPlayerImage;
/**
* Constructor for the map
*
* @param canvas : the canvas that holds the panel
*/
public MapPanel (Canvas canvas) {
myCanvas = canvas;
myMap = new EditableMap();
myInput = new Input(INPUT_DIR, this);
myInput.addListenerTo(this);
myWidth = 0;
myHeight = 0;
myCurrentLayer = 0;
myMaxLayer = 0;
myTileWidth = 0;
myTileHeight = 0;
myPlayerImage = ResourceManager.getInstance().<BufferedImage> getFile(PLAYER_IMAGE_PATH,
BufferedImage.class);
setPanelSize();
}
/**
* Set the panel and camera view according to the size user entered
*/
private void setPanelSize () {
Dimension d = new Dimension(myTileWidth * myWidth, myTileHeight * myHeight);
setPreferredSize(d);
Camera.instance().setMapSize(d);
Camera.instance().setViewSize(d);
Camera.instance().setWorldLocation(new Location3D((myTileWidth * myWidth)/2, (myTileHeight * myHeight)/2,0));
}
/**
* Paint the map on this panel
*/
@Override
public void paintComponent (Graphics g) {
g.setColor(Color.white);
g.fillRect(0, 0, 2*myWidth * myTileWidth, myHeight * myTileHeight);
Camera.instance().paint((Graphics2D)g);
g.setColor(Color.gray);
for (int i = 0; i < myWidth; i++) {
drawLineTest(i * myTileWidth / 2, 0, i * myTileWidth / 2, myHeight * myTileHeight/2,g);
}
for (int j = 0; j < myHeight; j++) {
drawLineTest(0, j * myTileHeight /2 , myWidth * myTileWidth / 2, j * myTileHeight /2,g);
}
((Graphics2D) g).setStroke(new BasicStroke(2));
g.setColor(Color.black);
drawLineTest(0, 0, myWidth * myTileWidth/2, 0, g);
drawLineTest(0, 0, 0, myHeight * myTileHeight/2,g);
drawLineTest(myWidth * myTileWidth/2, 0, myWidth * myTileWidth/2, myHeight * myTileHeight/2,g);
drawLineTest(0, myHeight * myTileHeight/2, myWidth * myTileWidth/2, myHeight * myTileHeight/2,g);
myMap.paint((Graphics2D)g);
for(Location loc : myMap.getAllPlayers().values()) {
Point2D view = Camera.instance().worldToView(new Location3D(loc));
g.drawImage(myPlayerImage, (int)view.getX(), (int)view.getY(), null);
}
}
/**
* Helper method to draw a line between two point
*
* @param x1 x value of the start point
* @param y1 y value of the start point
* @param x2 x value of the end point
* @param y2 y value of the end point
* @param g Graphics to draw the line
*/
public void drawLineTest(int x1, int y1, int x2, int y2, Graphics g) {
Point p1 = new Point(x1,y1);
Point2D loc1 = Camera.instance().worldToView(new Location3D(p1));
Point p2 = new Point(x2,y2);
Point2D loc2 = Camera.instance().worldToView(new Location3D(p2));
g.drawLine((int)loc1.getX(), (int)loc1.getY(), (int)loc2.getX(), (int)loc2.getY());
}
/**
* Set the width of the panel
* @param w
*/
public void setWidth (int w) {
myWidth = w;
setPanelSize();
repaint();
}
/**
* Set the height of the panel
* @param h
*/
public void setHeight (int h) {
myHeight = h;
setPanelSize();
repaint();
}
/**
* Set the tile width of the panel
* @param w
*/
public void setTileWidth (int w) {
myTileWidth = w;
setPanelSize();
repaint();
}
/**
* Set the tile height of the panel
* @param h
*/
public void setTileHeight (int h) {
myTileHeight = h;
setPanelSize();
repaint();
}
/**
* Set the map for the panel
* @param map
*/
public void setMap(EditableMap map) {
myMap = map;
}
/**
* Initialize the map by user's customization
*
* @param name
* @param desc
* @param width
* @param height
* @param tileWidth
* @param tileHeight
*/
public void initializeMap (String name, String desc, int width, int height, int tileWidth, int tileHeight) {
myMap = new EditableMap(name,desc,width, height, tileWidth, tileHeight);
}
/**
* place resource on the map according to the give location3D
* @param loc
*/
public void placeResource (Location3D loc) {
EditableResource r = myCanvas.getCurrentSelectResource();
myMap.addResource(r.getImage(), loc, r.getMyID(), r.getType(), r.getMyImageName(), r.getMyAmount());
repaint();
}
/**
* place terrain on the map according to the give location3D
* @param loc
*/
public void placeTerrain (Location3D loc) {
EditableTerrain t = myCanvas.getCurrentSelectTerrain();
myMap.addTerrain(t.getImage(), loc, t.getMyID(), t.getMyName(), t.getMyImageName(), t.getMyWalkAbility());
repaint();
}
/**
* place tile on the map according to the give location3D
* @param loc
*/
private void placeTile (Location3D loc) {
EditableTile t = myCanvas.getCurrentSelectTile();
myMap.addTile(loc, t.getMyID(), t.getMyName(), t.getMyImageName(), t.getImage());
repaint();
}
/**
* place player on the map according to the give location3D
* @param loc
*/
public void placePlayer (Location3D loc) {
myMap.addPlayer(new Location(loc.getX(),loc.getY()));
repaint();
}
/**
* set the edit mode as fill
*/
public void fill() {
myMode = FILLMODE;
}
/**
* Set the edit mode as remove
*/
public void setRemoveMode() {
myMode = REMOVEMODE;
}
/**
* remove terrains and resources from the current location
*
* @param loc
*/
public void remove(Location3D loc) {
myMap.getTerrain().remove(myMap.getTerrain().getItem(loc));
myMap.getResources().remove(myMap.getResources().getItem(loc));
repaint();
}
/**
* fill the map with current selected file
*/
public void fillTiles() {
EditableTile t = myCanvas.getCurrentSelectTile();
for(int i = 0; i<myMap.getMyXsize(); ++i) {
for(int j = 0; j<myMap.getMyYsize(); ++j) {
if (myMap.getMyTile(i, j).getMyID() == 0) {
myMap.addTile(i,j, t.getMyID(), t.getMyName(), t.getMyImageName(), t.getImage());
}
}
}
repaint();
}
/**
* clear the map
*/
public void clear () {
myCurrentLayer = 0;
myMaxLayer = 0;
myMap.clearMap();
repaint();
}
/**
*
* @return the map of the panel
*/
public EditableMap getMyMap () {
return myMap;
}
/**
* set the edit mode according to the given mode
* @param mode
*/
public void setMode (int mode) {
myMode = mode;
}
/**
* set the current layer according to the given number
* @param n
*/
public void setCurrentLayer (int n) {
myCurrentLayer = n;
}
/**
*
* @return the current layer user are editing
*/
public int getCurrentLayer () {
return myCurrentLayer;
}
/**
*
* @return the max layer for the map
*/
public int getMaxLayer () {
return myMaxLayer;
}
/**
* add one layer to the map
*/
public void addLayer () {
myMaxLayer++;
}
/**
* remove one layer from the map
*/
public void removeLayer () {
if(myMaxLayer>0)
myMaxLayer--;
}
/**
* edit the map according to the current mode
* @param p
*/
@InputMethodTarget(name = "onLeftMouseDown")
public void editMap (PositionObject p) {
Location3D loc = Camera.instance().viewtoWorld(p.getPoint2D());
switch (myMode) {
case RESOURCEMODE:
placeResource(loc);
break;
case PLAYERMODE:
placePlayer(loc);
break;
case TERRAINMODE:
placeTerrain(loc);
break;
case TILEMODE:
placeTile(loc);
break;
case FILLMODE:
fillTiles();
break;
case REMOVEMODE:
remove(loc);
default:
break;
}
}
/**
* support drag for tile editing
* @param p
*/
@InputMethodTarget(name = "onMouseDrag")
public void testDrag (PositionObject p) {
Location3D loc = Camera.instance().viewtoWorld(p.getPoint2D());
if (myMode == TILEMODE) {
placeTile(loc);
}
}
}