Files
ATCS/hacked-libtiled/tiled/core/Map.java
Zukero fe62c05b4b Fixed many bugs in the TMX Maps management. Added the
removeQuestProgress dialogue reward type. Initiallized the GDEVisitor
class to help with finding dependencies (through the Beanshell console
only for now).
2017-07-26 15:50:50 +02:00

475 lines
14 KiB
Java

/*
* Copyright 2004-2010, Thorbjørn Lindeijer <thorbjorn@lindeijer.nl>
* Copyright 2004-2006, Adam Turk <aturk@biggeruniverse.com>
*
* This file is part of libtiled-java.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* 1. Redistributions of source code must retain the above copyright notice,
* this list of conditions and the following disclaimer.
*
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE CONTRIBUTORS ``AS IS'' AND ANY EXPRESS OR
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO
* EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
* OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
* WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
* OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
* ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
package tiled.core;
import java.awt.Rectangle;
import java.util.Iterator;
import java.util.Properties;
import java.util.Vector;
/**
* The Map class is the focal point of the <code>tiled.core</code> package.
*/
public class Map implements Iterable<MapLayer>
{
public static final int ORIENTATION_ORTHOGONAL = 1;
public static final int ORIENTATION_ISOMETRIC = 2;
public static final int ORIENTATION_HEXAGONAL = 4;
/** Shifted (used for iso and hex). */
public static final int ORIENTATION_SHIFTED = 5;
private Vector<MapLayer> layers;
private Vector<ObjectGroup> objectGroups;
private Vector<TileLayer> tileLayers;
private Vector<TileSet> tileSets;
private int tileWidth, tileHeight;
private int orientation = ORIENTATION_ORTHOGONAL;
private Properties properties;
private String filename;
protected Rectangle bounds; // in tiles
/**
* @param width the map width in tiles.
* @param height the map height in tiles.
*/
public Map(int width, int height) {
layers = new Vector<MapLayer>();
bounds = new Rectangle(width, height);
properties = new Properties();
tileSets = new Vector<TileSet>();
objectGroups = new Vector<ObjectGroup>();
tileLayers = new Vector<TileLayer>();
}
/**
* Returns the total number of layers.
*
* @return the size of the layer vector
*/
public int getLayerCount() {
return layers.size();
}
/**
* Changes the bounds of this plane to include all layers completely.
*/
public void fitBoundsToLayers() {
int width = 0;
int height = 0;
Rectangle layerBounds = new Rectangle();
for (int i = 0; i < layers.size(); i++) {
getLayer(i).getBounds(layerBounds);
if (width < layerBounds.width) width = layerBounds.width;
if (height < layerBounds.height) height = layerBounds.height;
}
setBounds(width, height);
}
/**
* Returns a <code>Rectangle</code> representing the maximum bounds in
* tiles.
* @return a new rectangle containing the maximum bounds of this plane
*/
public Rectangle getBounds() {
return new Rectangle(bounds);
}
public void setBounds(int width, int height) {
bounds.width = width;
bounds.height = height;
}
public MapLayer addLayer(MapLayer layer) {
layer.setMap(this);
if (layer instanceof TileLayer) {
tileLayers.add((TileLayer) layer);
layers.add(layer);
} else if (layer instanceof ObjectGroup) {
layers.insertElementAt(layer, objectGroups.size());
objectGroups.add((ObjectGroup) layer);
} else {
layers.add(layer);
}
return layer;
}
public void setLayer(int index, MapLayer layer) {
layer.setMap(this);
layers.set(index, layer);
if (layer instanceof TileLayer) {
tileLayers.set(index - objectGroups.size(), (TileLayer) layer);
} else if (layer instanceof ObjectGroup) {
objectGroups.set(index, (ObjectGroup) layer);
}
}
public void insertLayer(int index, MapLayer layer) {
layer.setMap(this);
layers.add(index, layer);
if (layer instanceof TileLayer) {
tileLayers.add(index - objectGroups.size(), (TileLayer) layer);
} else if (layer instanceof ObjectGroup) {
objectGroups.add(index, (ObjectGroup) layer);
}
}
/**
* Removes the layer at the specified index. Layers above this layer will
* move down to fill the gap.
*
* @param index the index of the layer to be removed
* @return the layer that was removed from the list
*/
public MapLayer removeLayer(int index) {
if (index < objectGroups.size()) {
objectGroups.remove(index);
} else if (index - objectGroups.size() < tileLayers.size()){
tileLayers.remove(index - objectGroups.size());
}
return layers.remove(index);
}
/**
* Removes all layers from the plane.
*/
public void removeAllLayers() {
layers.removeAllElements();
objectGroups.removeAllElements();
tileLayers.removeAllElements();
}
/**
* Returns the layer vector.
*
* @return Vector the layer vector
*/
public Vector<MapLayer> getLayers() {
return layers;
}
/**
* Returns the tile layer vector.
*
* @return Vector the tile layer vector
*/
public Vector<TileLayer> getTileLayers() {
return tileLayers;
}
/**
* Returns the object group vector.
*
* @return Vector the object group vector
*/
public Vector<ObjectGroup> getObjectGroup() {
return objectGroups;
}
/**
* Sets the layer vector to the given java.util.Vector.
*
* @param layers the new set of layers
*/
public void setLayers(Vector<MapLayer> layers) {
this.layers = layers;
}
/**
* Returns the layer at the specified vector index.
*
* @param i the index of the layer to return
* @return the layer at the specified index, or null if the index is out of
* bounds
*/
public MapLayer getLayer(int i) {
try {
return layers.get(i);
} catch (ArrayIndexOutOfBoundsException e) {
}
return null;
}
/**
* Resizes this plane. The (dx, dy) pair determines where the original
* plane should be positioned on the new area. Only layers that exactly
* match the bounds of the map are resized, any other layers are moved by
* the given shift.
*
* @see tiled.core.MapLayer#resize
*
* @param width The new width of the map.
* @param height The new height of the map.
* @param dx The shift in x direction in tiles.
* @param dy The shift in y direction in tiles.
*/
public void resize(int width, int height, int dx, int dy) {
for (MapLayer layer : this) {
if (layer.bounds.equals(bounds)) {
layer.resize(width, height, dx, dy);
} else {
layer.setOffset(layer.bounds.x + dx, layer.bounds.y + dy);
}
}
bounds.width = width;
bounds.height = height;
}
/**
* Determines whether the point (x,y) falls within the plane.
*
* @param x
* @param y
* @return <code>true</code> if the point is within the plane,
* <code>false</code> otherwise
*/
public boolean inBounds(int x, int y) {
return x >= 0 && y >= 0 && x < bounds.width && y < bounds.height;
}
public Iterator<MapLayer> iterator() {
return layers.iterator();
}
/**
* Adds a Tileset to this Map. If the set is already attached to this map,
* <code>addTileset</code> simply returns.
*
* @param tileset a tileset to add
*/
public void addTileset(TileSet tileset) {
if (tileset == null || tileSets.indexOf(tileset) > -1) {
return;
}
Tile t = tileset.getTile(0);
if (t != null) {
int tw = t.getWidth();
int th = t.getHeight();
if (tw != tileWidth) {
if (tileWidth == 0) {
tileWidth = tw;
tileHeight = th;
}
}
}
tileSets.add(tileset);
}
/**
* Removes a {@link TileSet} from the map, and removes any tiles in the set
* from the map layers.
*
* @param tileset TileSet to remove
*/
public void removeTileset(TileSet tileset) {
// Sanity check
final int tilesetIndex = tileSets.indexOf(tileset);
if (tilesetIndex == -1)
return;
// Go through the map and remove any instances of the tiles in the set
for (Tile tile : tileset) {
for (MapLayer ml : this) {
if (ml instanceof TileLayer) {
((TileLayer) ml).removeTile(tile);
}
}
}
tileSets.remove(tileset);
}
/**
* @return the map properties
*/
public Properties getProperties() {
return properties;
}
public void setProperties(Properties prop) {
properties = prop;
}
public void setFilename(String filename) {
this.filename = filename;
}
/**
* Sets a new tile width.
*
* @param width the new tile width
*/
public void setTileWidth(int width) {
tileWidth = width;
}
/**
* Sets a new tile height.
*
* @param height the new tile height
*/
public void setTileHeight(int height) {
tileHeight = height;
}
public void setOrientation(int orientation) {
this.orientation = orientation;
}
public String getFilename() {
return filename;
}
/**
* Returns a vector with the currently loaded tileSets.
*
* @return Vector
*/
public Vector<TileSet> getTileSets() {
return tileSets;
}
/**
* Returns width of map in tiles.
*
* @return int
*/
public int getWidth() {
return bounds.width;
}
/**
* Returns height of map in tiles.
*
* @return int
*/
public int getHeight() {
return bounds.height;
}
/**
* Returns default tile width for this map.
*
* @return the default tile width
*/
public int getTileWidth() {
return tileWidth;
}
/**
* Returns default tile height for this map.
*
* @return the default tile height
*/
public int getTileHeight() {
return tileHeight;
}
/**
* Returns wether the given tile coordinates fall within the map
* boundaries.
*
* @param x The tile-space x-coordinate
* @param y The tile-space y-coordinate
* @return <code>true</code> if the point is within the map boundaries,
* <code>false</code> otherwise
*/
public boolean contains(int x, int y) {
return x >= 0 && y >= 0 && x < bounds.width && y < bounds.height;
}
/**
* Returns the maximum tile height. This is the height of the highest tile
* in all tileSets or the tile height used by this map if it's smaller.
*
* @return int The maximum tile height
*/
public int getTileHeightMax() {
int maxHeight = tileHeight;
for (TileSet tileset : tileSets) {
int height = tileset.getTileHeight();
if (height > maxHeight) {
maxHeight = height;
}
}
return maxHeight;
}
/**
* Swaps the tile sets at the given indices.
*/
public void swapTileSets(int index0, int index1) {
if (index0 == index1) return;
TileSet set = tileSets.get(index0);
tileSets.set(index0, tileSets.get(index1));
tileSets.set(index1, set);
}
/**
* Returns the orientation of this map. Orientation will be one of
* {@link Map#ORIENTATION_ISOMETRIC}, {@link Map#ORIENTATION_ORTHOGONAL},
* {@link Map#ORIENTATION_HEXAGONAL} and {@link Map#ORIENTATION_SHIFTED}.
*
* @return The orientation from the enumerated set
*/
public int getOrientation() {
return orientation;
}
/**
* Returns string describing the map. The form is <code>Map[width x height
* x layers][tileWidth x tileHeight]</code>, for example <code>
* Map[64x64x2][24x24]</code>.
*
* @return string describing map
*/
public String toString() {
return "Map[" + bounds.width + "x" + bounds.height + "x" +
getLayerCount() + "][" + tileWidth + "x" +
tileHeight + "]";
}
public boolean containsLayer(MapLayer layer) {
return layers.contains(layer);
}
public int getLayerIndex(MapLayer layer) {
return layers.indexOf(layer);
}
}