All Downloads are FREE. Search and download functionalities are using the official Maven repository.

com.github.mathiewz.slick.tiled.TiledMap Maven / Gradle / Ivy

Go to download

The main purpose of this libraryis to modernize and maintain the slick2D library.

The newest version!
package com.github.mathiewz.slick.tiled;

import java.io.ByteArrayInputStream;
import java.io.InputStream;
import java.util.ArrayList;
import java.util.Properties;

import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;

import org.w3c.dom.Document;
import org.w3c.dom.Element;
import org.w3c.dom.NodeList;
import org.xml.sax.InputSource;

import com.github.mathiewz.slick.Image;
import com.github.mathiewz.slick.SlickException;
import com.github.mathiewz.slick.util.Log;
import com.github.mathiewz.slick.util.ResourceLoader;

/**
 * This class is intended to parse TilED maps. TilED is a generic tool for tile
 * map editing and can be found at:
 *
 * http://mapeditor.org/
 *
 * @author kevin
 * @author Tiago Costa
 * @author Loads of others!
 */
public class TiledMap {
    /** Indicates if we're running on a headless system */
    private static boolean headless;

    /** The width of the map */
    protected int width;
    /** The height of the map */
    protected int height;
    /** The width of the tiles used on the map */
    protected int tileWidth;
    /** The height of the tiles used on the map */
    protected int tileHeight;

    /** The location prefix where we can find tileset images */
    protected String tilesLocation;

    /** the properties of the map */
    protected Properties props;

    /** The list of tilesets defined in the map */
    protected ArrayList tileSets = new ArrayList<>();
    /** The list of layers defined in the map */
    protected ArrayList layers = new ArrayList<>();
    /** The list of object-groups defined in the map */
    protected ArrayList objectGroups = new ArrayList<>();

    /** Indicates a orthogonal map */
    protected static final int ORTHOGONAL = 1;
    /** Indicates an isometric map */
    protected static final int ISOMETRIC = 2;

    /** The orientation of this map */
    protected int orientation;

    /** True if we want to load tilesets - including their image data */
    private boolean loadTileSets = true;

    /**
     * Create a new tile map based on a given TMX file
     *
     * @param ref
     *            The location of the tile map to load
     */
    public TiledMap(String ref) {
        this(ref, true);
    }

    /**
     * Create a new tile map based on a given TMX file
     *
     * @param ref
     *            The location of the tile map to load
     * @param loadTileSets
     *            True if we want to load tilesets - including their image data
     */
    public TiledMap(String ref, boolean loadTileSets) {
        this.loadTileSets = loadTileSets;
        ref = ref.replace('\\', '/');
        load(ResourceLoader.getResourceAsStream(ref), ref.substring(0, ref.lastIndexOf("/")));
    }

    /**
     * Create a new tile map based on a given TMX file
     *
     * @param ref
     *            The location of the tile map to load
     * @param tileSetsLocation
     *            The location where we can find the tileset images and other
     *            resources
     */
    public TiledMap(String ref, String tileSetsLocation) {
        load(ResourceLoader.getResourceAsStream(ref), tileSetsLocation);
    }

    /**
     * Load a tile map from an arbitary input stream
     *
     * @param in
     *            The input stream to load from
     */
    public TiledMap(InputStream in) {
        load(in, "");
    }

    /**
     * Load a tile map from an arbitary input stream
     *
     * @param in
     *            The input stream to load from
     * @param tileSetsLocation
     *            The location at which we can find tileset images
     */
    public TiledMap(InputStream in, String tileSetsLocation) {
        load(in, tileSetsLocation);
    }

    /**
     * Get the location of the tile images specified
     *
     * @return The location of the tile images specified as a resource reference
     *         prefix
     */
    public String getTilesLocation() {
        return tilesLocation;
    }

    /**
     * Get the index of the layer with given name
     *
     * @param name
     *            The name of the tile to search for
     * @return The index of the layer or -1 if there is no layer with given name
     */
    public int getLayerIndex(String name) {
        for (int i = 0; i < layers.size(); i++) {
            Layer layer = layers.get(i);

            if (layer.name.equals(name)) {
                return i;
            }
        }

        return -1;
    }

    /**
     * Gets the Image used to draw the tile at the given x and y coordinates.
     *
     * @param x
     *            The x coordinate of the tile whose image should be retrieved
     * @param y
     *            The y coordinate of the tile whose image should be retrieved
     * @param layerIndex
     *            The index of the layer on which the tile whose image should be
     *            retrieve exists
     * @return The image used to draw the specified tile or null if there is no
     *         image for the specified tile.
     */
    public Image getTileImage(int x, int y, int layerIndex) {
        Layer layer = layers.get(layerIndex);

        int tileSetIndex = layer.data[x][y][0];
        if (tileSetIndex >= 0 && tileSetIndex < tileSets.size()) {
            TileSet tileSet = tileSets.get(tileSetIndex);

            int sheetX = tileSet.getTileX(layer.data[x][y][1]);
            int sheetY = tileSet.getTileY(layer.data[x][y][1]);

            return tileSet.tiles.getSprite(sheetX, sheetY);
        }

        return null;
    }

    /**
     * Get the width of the map
     *
     * @return The width of the map (in tiles)
     */
    public int getWidth() {
        return width;
    }

    /**
     * Get the height of the map
     *
     * @return The height of the map (in tiles)
     */
    public int getHeight() {
        return height;
    }

    /**
     * Get the height of a single tile
     *
     * @return The height of a single tile (in pixels)
     */
    public int getTileHeight() {
        return tileHeight;
    }

    /**
     * Get the width of a single tile
     *
     * @return The height of a single tile (in pixels)
     */
    public int getTileWidth() {
        return tileWidth;
    }

    /**
     * Get the global ID of a tile at specified location in the map
     *
     * @param x
     *            The x location of the tile
     * @param y
     *            The y location of the tile
     * @param layerIndex
     *            The index of the layer to retireve the tile from
     * @return The global ID of the tile
     */
    public int getTileId(int x, int y, int layerIndex) {
        Layer layer = layers.get(layerIndex);
        return layer.getTileID(x, y);
    }

    /**
     * Set the global ID of a tile at specified location in the map
     *
     * @param x
     *            The x location of the tile
     * @param y
     *            The y location of the tile
     * @param layerIndex
     *            The index of the layer to set the new tileid
     * @param tileid
     *            The tileid to be set
     */
    public void setTileId(int x, int y, int layerIndex, int tileid) {
        Layer layer = layers.get(layerIndex);
        layer.setTileID(x, y, tileid);
    }

    /**
     * Get a property given to the map. Note that this method will not perform
     * well and should not be used as part of the default code path in the game
     * loop.
     *
     * @param propertyName
     *            The name of the property of the map to retrieve
     * @param def
     *            The default value to return
     * @return The value assigned to the property on the map (or the default
     *         value if none is supplied)
     */
    public String getMapProperty(String propertyName, String def) {
        if (props == null) {
            return def;
        }
        return props.getProperty(propertyName, def);
    }

    /**
     * Get a property given to a particular layer. Note that this method will
     * not perform well and should not be used as part of the default code path
     * in the game loop.
     *
     * @param layerIndex
     *            The index of the layer to retrieve
     * @param propertyName
     *            The name of the property of this layer to retrieve
     * @param def
     *            The default value to return
     * @return The value assigned to the property on the layer (or the default
     *         value if none is supplied)
     */
    public String getLayerProperty(int layerIndex, String propertyName, String def) {
        Layer layer = layers.get(layerIndex);
        if (layer == null || layer.props == null) {
            return def;
        }
        return layer.props.getProperty(propertyName, def);
    }

    /**
     * Get a propety given to a particular tile. Note that this method will not
     * perform well and should not be used as part of the default code path in
     * the game loop.
     *
     * @param tileID
     *            The global ID of the tile to retrieve
     * @param propertyName
     *            The name of the property to retireve
     * @param def
     *            The default value to return
     * @return The value assigned to the property on the tile (or the default
     *         value if none is supplied)
     */
    public String getTileProperty(int tileID, String propertyName, String def) {
        if (tileID == 0) {
            return def;
        }

        TileSet set = findTileSet(tileID);

        Properties props = set.getProperties(tileID);
        if (props == null) {
            return def;
        }
        return props.getProperty(propertyName, def);
    }

    /**
     * Render the whole tile map at a given location
     *
     * @param x
     *            The x location to render at
     * @param y
     *            The y location to render at
     */
    public void render(int x, int y) {
        render(x, y, 0, 0, width, height, false);
    }

    /**
     * Render a single layer from the map
     *
     * @param x
     *            The x location to render at
     * @param y
     *            The y location to render at
     * @param layer
     *            The layer to render
     */
    public void render(int x, int y, int layer) {
        render(x, y, 0, 0, getWidth(), getHeight(), layer, false);
    }

    /**
     * Render a section of the tile map
     *
     * @param x
     *            The x location to render at
     * @param y
     *            The y location to render at
     * @param sx
     *            The x tile location to start rendering
     * @param sy
     *            The y tile location to start rendering
     * @param width
     *            The width of the section to render (in tiles)
     * @param height
     *            The height of the secton to render (in tiles)
     */
    public void render(int x, int y, int sx, int sy, int width, int height) {
        render(x, y, sx, sy, width, height, false);
    }

    /**
     * Render a section of the tile map
     *
     * @param x
     *            The x location to render at
     * @param y
     *            The y location to render at
     * @param sx
     *            The x tile location to start rendering
     * @param sy
     *            The y tile location to start rendering
     * @param width
     *            The width of the section to render (in tiles)
     * @param height
     *            The height of the secton to render (in tiles)
     * @param l
     *            The index of the layer to render
     * @param lineByLine
     *            True if we should render line by line, i.e. giving us a chance
     *            to render something else between lines (@see
     *            {@link #renderedLine(int, int, int)}
     */
    public void render(int x, int y, int sx, int sy, int width, int height, int l, boolean lineByLine) {
        Layer layer = layers.get(l);

        switch (orientation) {
            case ORTHOGONAL:
                for (int ty = 0; ty < height; ty++) {
                    layer.render(x, y, sx, sy, width, ty, lineByLine, tileWidth, tileHeight);
                }
                break;
            case ISOMETRIC:
                renderIsometricMap(x, y, sx, sy, width, height, layer, lineByLine);
                break;
            default:
                // log error or something
        }
    }

    /**
     * Render a section of the tile map
     *
     * @param x
     *            The x location to render at
     * @param y
     *            The y location to render at
     * @param sx
     *            The x tile location to start rendering
     * @param sy
     *            The y tile location to start rendering
     * @param width
     *            The width of the section to render (in tiles)
     * @param height
     *            The height of the secton to render (in tiles)
     * @param lineByLine
     *            True if we should render line by line, i.e. giving us a chance
     *            to render something else between lines (@see
     *            {@link #renderedLine(int, int, int)}
     */
    public void render(int x, int y, int sx, int sy, int width, int height, boolean lineByLine) {
        switch (orientation) {
            case ORTHOGONAL:
                for (int ty = 0; ty < height; ty++) {
                    for (int i = 0; i < layers.size(); i++) {
                        Layer layer = layers.get(i);
                        layer.render(x, y, sx, sy, width, ty, lineByLine, tileWidth, tileHeight);
                    }
                }
                break;
            case ISOMETRIC:
                renderIsometricMap(x, y, sx, sy, width, height, null, lineByLine);
                break;
            default:
                // log error or something
        }
    }

    /**
     * Render of isometric map renders.
     *
     * @param x
     *            The x location to render at
     * @param y
     *            The y location to render at
     * @param sx
     *            The x tile location to start rendering
     * @param sy
     *            The y tile location to start rendering
     * @param width
     *            The width of the section to render (in tiles)
     * @param height
     *            The height of the section to render (in tiles)
     * @param layer
     *            if this is null all layers are rendered, if not only the
     *            selected layer is renderered
     * @param lineByLine
     *            True if we should render line by line, i.e. giving us a chance
     *            to render something else between lines (@see
     *            {@link #renderedLine(int, int, int)}
     *
     *            TODO: [Isometric map] Render stuff between lines, concept of
     *            line differs from ortho maps
     */
    protected void renderIsometricMap(int x, int y, int sx, int sy, int width, int height, Layer layer, boolean lineByLine) {
        ArrayList drawLayers = layers;
        if (layer != null) {
            drawLayers = new ArrayList<>();
            drawLayers.add(layer);
        }

        int maxCount = width * height;
        int allCount = 0;

        boolean allProcessed = false;

        int initialLineX = x;
        int initialLineY = y;

        int startLineTileX = 0;
        int startLineTileY = 0;
        while (!allProcessed) {

            int currentTileX = startLineTileX;
            int currentTileY = startLineTileY;
            int currentLineX = initialLineX;

            int min = 0;
            if (height > width) {
                min = startLineTileY < width - 1 ? startLineTileY : width - currentTileX < height ? width - currentTileX - 1 : width - 1;
            } else {
                min = startLineTileY < height - 1 ? startLineTileY : width - currentTileX < height ? width - currentTileX - 1 : height - 1;
            }

            for (int burner = 0; burner <= min; currentTileX++, currentTileY--, burner++) {
                for (int layerIdx = 0; layerIdx < drawLayers.size(); layerIdx++) {
                    Layer currentLayer = drawLayers.get(layerIdx);
                    currentLayer.render(currentLineX, initialLineY, currentTileX, currentTileY, 1, 0, lineByLine, tileWidth, tileHeight);
                }
                currentLineX += tileWidth;

                allCount++;
            }

            // System.out.println("Line : " + counter++ + " - " + count +
            // "allcount : " + allCount);

            if (startLineTileY < height - 1) {
                startLineTileY += 1;
                initialLineX -= tileWidth / 2;
                initialLineY += tileHeight / 2;
            } else {
                startLineTileX += 1;
                initialLineX += tileWidth / 2;
                initialLineY += tileHeight / 2;
            }

            if (allCount >= maxCount) {
                allProcessed = true;
            }
        }
    }

    /**
     * Retrieve a count of the number of layers available
     *
     * @return The number of layers available in this map
     */
    public int getLayerCount() {
        return layers.size();
    }

    /**
     * Save parser for strings to ints
     *
     * @param value
     *            The string to parse
     * @return The integer to parse or zero if the string isn't an int
     */
    private int parseInt(String value) {
        try {
            return Integer.parseInt(value);
        } catch (NumberFormatException e) {
            return 0;
        }
    }

    /**
     * Load a TilED map
     *
     * @param in
     *            The input stream from which to load the map
     * @param tileSetsLocation
     *            The location from which we can retrieve tileset images
     */
    private void load(InputStream in, String tileSetsLocation) {
        tilesLocation = tileSetsLocation;

        try {
            DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
            factory.setValidating(false);
            DocumentBuilder builder = factory.newDocumentBuilder();
            builder.setEntityResolver((publicId, systemId) -> new InputSource(new ByteArrayInputStream(new byte[0])));

            Document doc = builder.parse(in);
            Element docElement = doc.getDocumentElement();

            if (docElement.getAttribute("orientation").equals("orthogonal")) {
                orientation = ORTHOGONAL;
            } else {
                orientation = ISOMETRIC;
            }

            width = parseInt(docElement.getAttribute("width"));
            height = parseInt(docElement.getAttribute("height"));
            tileWidth = parseInt(docElement.getAttribute("tilewidth"));
            tileHeight = parseInt(docElement.getAttribute("tileheight"));

            // now read the map properties
            Element propsElement = (Element) docElement.getElementsByTagName("properties").item(0);
            if (propsElement != null) {
                NodeList properties = propsElement.getElementsByTagName("property");
                if (properties != null) {
                    props = new Properties();
                    for (int p = 0; p < properties.getLength(); p++) {
                        Element propElement = (Element) properties.item(p);

                        String name = propElement.getAttribute("name");
                        String value = propElement.getAttribute("value");
                        props.setProperty(name, value);
                    }
                }
            }

            if (loadTileSets) {
                TileSet tileSet = null;
                TileSet lastSet = null;

                NodeList setNodes = docElement.getElementsByTagName("tileset");
                for (int i = 0; i < setNodes.getLength(); i++) {
                    Element current = (Element) setNodes.item(i);

                    tileSet = new TileSet(this, current, !headless);
                    tileSet.index = i;

                    if (lastSet != null) {
                        lastSet.setLimit(tileSet.firstGID - 1);
                    }
                    lastSet = tileSet;

                    tileSets.add(tileSet);
                }
            }

            NodeList layerNodes = docElement.getElementsByTagName("layer");
            for (int i = 0; i < layerNodes.getLength(); i++) {
                Element current = (Element) layerNodes.item(i);
                Layer layer = new Layer(this, current);
                layer.index = i;

                layers.add(layer);
            }

            // acquire object-groups
            NodeList objectGroupNodes = docElement.getElementsByTagName("objectgroup");

            for (int i = 0; i < objectGroupNodes.getLength(); i++) {
                Element current = (Element) objectGroupNodes.item(i);
                ObjectGroup objectGroup = new ObjectGroup(current);
                objectGroup.index = i;

                objectGroups.add(objectGroup);
            }
        } catch (Exception e) {
            Log.error(e);
            throw new SlickException("Failed to parse tilemap", e);
        }
    }

    /**
     * Retrieve the number of tilesets available in this map
     *
     * @return The number of tilesets available in this map
     */
    public int getTileSetCount() {
        return tileSets.size();
    }

    /**
     * Get a tileset at a particular index in the list of sets for this map
     *
     * @param index
     *            The index of the tileset.
     * @return The TileSet requested
     */
    public TileSet getTileSet(int index) {
        return tileSets.get(index);
    }

    /**
     * Get a tileset by a given global ID
     *
     * @param gid
     *            The global ID of the tileset to retrieve
     * @return The tileset requested or null if no tileset matches
     */
    public TileSet getTileSetByGID(int gid) {
        for (int i = 0; i < tileSets.size(); i++) {
            TileSet set = tileSets.get(i);

            if (set.contains(gid)) {
                return set;
            }
        }

        return null;
    }

    /**
     * Find a tile for a given global tile id
     *
     * @param gid
     *            The global tile id we're looking for
     * @return The tileset in which that tile lives or null if the gid is not
     *         defined
     */
    public TileSet findTileSet(int gid) {
        for (int i = 0; i < tileSets.size(); i++) {
            TileSet set = tileSets.get(i);

            if (set.contains(gid)) {
                return set;
            }
        }

        return null;
    }

    /**
     * Overrideable to allow other sprites to be rendered between lines of the
     * map
     *
     * @param visualY
     *            The visual Y coordinate, i.e. 0 to height
     * @param mapY
     *            The map Y coordinate, i.e. y to y+height
     * @param layer
     *            The layer being rendered
     */
    protected void renderedLine(int visualY, int mapY, int layer) {
    }

    /**
     * Returns the number of object-groups defined in the map.
     *
     * @return Number of object-groups on the map
     */
    public int getObjectGroupCount() {
        return objectGroups.size();
    }

    /**
     * Returns the number of objects of a specific object-group.
     *
     * @param groupID
     *            The index of this object-group
     * @return Number of the objects in the object-group or -1, when error
     *         occurred.
     */
    public int getObjectCount(int groupID) {
        if (groupID >= 0 && groupID < objectGroups.size()) {
            ObjectGroup grp = objectGroups.get(groupID);
            return grp.objects.size();
        }
        return -1;
    }

    /**
     * Return the name of a specific object from a specific group.
     *
     * @param groupID
     *            Index of a group
     * @param objectID
     *            Index of an object
     * @return The name of an object or null, when error occurred
     */
    public String getObjectName(int groupID, int objectID) {
        if (groupID >= 0 && groupID < objectGroups.size()) {
            ObjectGroup grp = objectGroups.get(groupID);
            if (objectID >= 0 && objectID < grp.objects.size()) {
                GroupObject object = grp.objects.get(objectID);
                return object.name;
            }
        }
        return null;
    }

    /**
     * Return the type of an specific object from a specific group.
     *
     * @param groupID
     *            Index of a group
     * @param objectID
     *            Index of an object
     * @return The type of an object or null, when error occurred
     */
    public String getObjectType(int groupID, int objectID) {
        if (groupID >= 0 && groupID < objectGroups.size()) {
            ObjectGroup grp = objectGroups.get(groupID);
            if (objectID >= 0 && objectID < grp.objects.size()) {
                GroupObject object = grp.objects.get(objectID);
                return object.type;
            }
        }
        return null;
    }

    /**
     * Returns the x-coordinate of a specific object from a specific group.
     *
     * @param groupID
     *            Index of a group
     * @param objectID
     *            Index of an object
     * @return The x-coordinate of an object, or -1, when error occurred
     */
    public int getObjectX(int groupID, int objectID) {
        if (groupID >= 0 && groupID < objectGroups.size()) {
            ObjectGroup grp = objectGroups.get(groupID);
            if (objectID >= 0 && objectID < grp.objects.size()) {
                GroupObject object = grp.objects.get(objectID);
                return object.x;
            }
        }
        return -1;
    }

    /**
     * Returns the y-coordinate of a specific object from a specific group.
     *
     * @param groupID
     *            Index of a group
     * @param objectID
     *            Index of an object
     * @return The y-coordinate of an object, or -1, when error occurred
     */
    public int getObjectY(int groupID, int objectID) {
        if (groupID >= 0 && groupID < objectGroups.size()) {
            ObjectGroup grp = objectGroups.get(groupID);
            if (objectID >= 0 && objectID < grp.objects.size()) {
                GroupObject object = grp.objects.get(objectID);
                return object.y;
            }
        }
        return -1;
    }

    /**
     * Returns the width of a specific object from a specific group.
     *
     * @param groupID
     *            Index of a group
     * @param objectID
     *            Index of an object
     * @return The width of an object, or -1, when error occurred
     */
    public int getObjectWidth(int groupID, int objectID) {
        if (groupID >= 0 && groupID < objectGroups.size()) {
            ObjectGroup grp = objectGroups.get(groupID);
            if (objectID >= 0 && objectID < grp.objects.size()) {
                GroupObject object = grp.objects.get(objectID);
                return object.width;
            }
        }
        return -1;
    }

    /**
     * Returns the height of a specific object from a specific group.
     *
     * @param groupID
     *            Index of a group
     * @param objectID
     *            Index of an object
     * @return The height of an object, or -1, when error occurred
     */
    public int getObjectHeight(int groupID, int objectID) {
        if (groupID >= 0 && groupID < objectGroups.size()) {
            ObjectGroup grp = objectGroups.get(groupID);
            if (objectID >= 0 && objectID < grp.objects.size()) {
                GroupObject object = grp.objects.get(objectID);
                return object.height;
            }
        }
        return -1;
    }

    /**
     * Retrieve the image source property for a given object
     *
     * @param groupID
     *            Index of a group
     * @param objectID
     *            Index of an object
     * @return The image source reference or null if one isn't defined
     */
    public String getObjectImage(int groupID, int objectID) {
        if (groupID >= 0 && groupID < objectGroups.size()) {
            ObjectGroup grp = objectGroups.get(groupID);
            if (objectID >= 0 && objectID < grp.objects.size()) {
                GroupObject object = grp.objects.get(objectID);

                if (object == null) {
                    return null;
                }

                return object.image;
            }
        }

        return null;
    }

    /**
     * Looks for a property with the given name and returns it's value. If no
     * property is found, def is returned.
     *
     * @param groupID
     *            Index of a group
     * @param objectID
     *            Index of an object
     * @param propertyName
     *            Name of a property
     * @param def
     *            default value to return, if no property is found
     * @return The value of the property with the given name or def, if there is
     *         no property with that name.
     */
    public String getObjectProperty(int groupID, int objectID, String propertyName, String def) {
        if (groupID >= 0 && groupID < objectGroups.size()) {
            ObjectGroup grp = objectGroups.get(groupID);
            if (objectID >= 0 && objectID < grp.objects.size()) {
                GroupObject object = grp.objects.get(objectID);

                if (object == null) {
                    return def;
                }
                if (object.props == null) {
                    return def;
                }

                return object.props.getProperty(propertyName, def);
            }
        }
        return def;
    }

    /**
     * A group of objects on the map (objects layer)
     *
     * @author kulpae
     */
    protected class ObjectGroup {
        /** The index of this group */
        public int index;
        /** The name of this group - read from the XML */
        public String name;
        /** The Objects of this group */
        public ArrayList objects;
        /** The width of this layer */
        public int width;
        /** The height of this layer */
        public int height;

        /** the properties of this group */
        public Properties props;

        /**
         * Create a new group based on the XML definition
         *
         * @param element
         *            The XML element describing the layer
         */
        public ObjectGroup(Element element) {
            name = element.getAttribute("name");
            width = Integer.parseInt(element.getAttribute("width"));
            height = Integer.parseInt(element.getAttribute("height"));
            objects = new ArrayList<>();

            // now read the layer properties
            Element propsElement = (Element) element.getElementsByTagName("properties").item(0);
            if (propsElement != null) {
                NodeList properties = propsElement.getElementsByTagName("property");
                if (properties != null) {
                    props = new Properties();
                    for (int p = 0; p < properties.getLength(); p++) {
                        Element propElement = (Element) properties.item(p);

                        String name = propElement.getAttribute("name");
                        String value = propElement.getAttribute("value");
                        props.setProperty(name, value);
                    }
                }
            }

            NodeList objectNodes = element.getElementsByTagName("object");
            for (int i = 0; i < objectNodes.getLength(); i++) {
                Element objElement = (Element) objectNodes.item(i);
                GroupObject object = new GroupObject(objElement);
                object.index = i;
                objects.add(object);
            }
        }
    }

    /**
     * An object from a object-group on the map
     *
     * @author kulpae
     */
    protected class GroupObject {
        /** The index of this object */
        public int index;
        /** The name of this object - read from the XML */
        public String name;
        /** The type of this object - read from the XML */
        public String type;
        /** The x-coordinate of this object */
        public int x;
        /** The y-coordinate of this object */
        public int y;
        /** The width of this object */
        public int width;
        /** The height of this object */
        public int height;
        /** The image source */
        private String image;

        /** the properties of this group */
        public Properties props;

        /**
         * Create a new group based on the XML definition
         *
         * @param element
         *            The XML element describing the layer
         */
        public GroupObject(Element element) {
            name = element.getAttribute("name");
            type = element.getAttribute("type");
            x = Integer.parseInt(element.getAttribute("x"));
            y = Integer.parseInt(element.getAttribute("y"));
            width = Integer.parseInt(element.getAttribute("width"));
            height = Integer.parseInt(element.getAttribute("height"));

            Element imageElement = (Element) element.getElementsByTagName("image").item(0);
            if (imageElement != null) {
                image = imageElement.getAttribute("source");
            }

            // now read the layer properties
            Element propsElement = (Element) element.getElementsByTagName("properties").item(0);
            if (propsElement != null) {
                NodeList properties = propsElement.getElementsByTagName("property");
                if (properties != null) {
                    props = new Properties();
                    for (int p = 0; p < properties.getLength(); p++) {
                        Element propElement = (Element) properties.item(p);

                        String name = propElement.getAttribute("name");
                        String value = propElement.getAttribute("value");
                        props.setProperty(name, value);
                    }
                }
            }
        }
    }

}




© 2015 - 2025 Weber Informatics LLC | Privacy Policy