📄 xmlmaptransformer.java
字号:
/* * Tiled Map Editor, (c) 2004-2006 * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * Adam Turk <aturk@biggeruniverse.com> * Bjorn Lindeijer <b.lindeijer@xs4all.nl> */package tiled.io.xml;import java.awt.Color;import java.awt.Image;import java.io.*;import java.lang.reflect.*;import java.net.MalformedURLException;import java.net.URL;import java.util.Properties;import java.util.zip.GZIPInputStream;import javax.imageio.ImageIO;import javax.xml.parsers.*;import org.w3c.dom.*;import org.xml.sax.SAXException;import tiled.core.*;import tiled.io.ImageHelper;import tiled.io.MapReader;import tiled.io.PluginLogger;import tiled.mapeditor.util.cutter.BasicTileCutter;import tiled.util.*;/** * @version $Id: XMLMapTransformer.java 683 2006-06-25 14:17:37Z bjorn $ */public class XMLMapTransformer implements MapReader{ private Map map; private String xmlPath; private PluginLogger logger; public XMLMapTransformer() { logger = new PluginLogger(); } private static String makeUrl(String filename) throws MalformedURLException { final String url; if (filename.indexOf("://") > 0 || filename.startsWith("file:")) { url = filename; } else { url = (new File(filename)).toURL().toString(); } return url; } private static int reflectFindMethodByName(Class c, String methodName) { Method[] methods = c.getMethods(); for (int i = 0; i < methods.length; i++) { if (methods[i].getName().equalsIgnoreCase(methodName)) { return i; } } return -1; } private void reflectInvokeMethod(Object invokeVictim, Method method, String[] args) throws InvocationTargetException, Exception { Class[] parameterTypes = method.getParameterTypes(); Object[] conformingArguments = new Object[parameterTypes.length]; if (args.length < parameterTypes.length) { throw new Exception("Insufficient arguments were supplied"); } for (int i = 0; i < parameterTypes.length; i++) { if ("int".equalsIgnoreCase(parameterTypes[i].getName())) { conformingArguments[i] = new Integer(args[i]); } else if ("float".equalsIgnoreCase(parameterTypes[i].getName())) { conformingArguments[i] = new Float(args[i]); } else if (parameterTypes[i].getName().endsWith("String")) { conformingArguments[i] = args[i]; } else if ("boolean".equalsIgnoreCase(parameterTypes[i].getName())) { conformingArguments[i] = Boolean.valueOf(args[i]); } else { logger.debug("Unsupported argument type " + parameterTypes[i].getName() + ", defaulting to java.lang.String"); conformingArguments[i] = args[i]; } } method.invoke(invokeVictim,conformingArguments); } private void setOrientation(String o) { if ("isometric".equalsIgnoreCase(o)) { map.setOrientation(Map.MDO_ISO); } else if ("orthogonal".equalsIgnoreCase(o)) { map.setOrientation(Map.MDO_ORTHO); } else if ("hexagonal".equalsIgnoreCase(o)) { map.setOrientation(Map.MDO_HEX); } else if ("oblique".equalsIgnoreCase(o)) { map.setOrientation(Map.MDO_OBLIQUE); } else if ("shifted".equalsIgnoreCase(o)) { map.setOrientation(Map.MDO_SHIFTED); } else { logger.warn("Unknown orientation '" + o + "'"); } } private static String getAttributeValue(Node node, String attribname) { NamedNodeMap attributes = node.getAttributes(); String att = null; if (attributes != null) { Node attribute = attributes.getNamedItem(attribname); if (attribute != null) { att = attribute.getNodeValue(); } } return att; } private static int getAttribute(Node node, String attribname, int def) { String attr = getAttributeValue(node, attribname); if (attr != null) { return Integer.parseInt(attr); } else { return def; } } private Object unmarshalClass(Class reflector, Node node) throws InstantiationException, IllegalAccessException, InvocationTargetException { Constructor cons = null; try { cons = reflector.getConstructor(null); } catch (SecurityException e1) { e1.printStackTrace(); } catch (NoSuchMethodException e1) { e1.printStackTrace(); return null; } Object o = cons.newInstance(null); Node n; Method[] methods = reflector.getMethods(); NamedNodeMap nnm = node.getAttributes(); if (nnm != null) { for (int i = 0; i < nnm.getLength(); i++) { n = nnm.item(i); try { int j = reflectFindMethodByName(reflector, "set" + n.getNodeName()); if (j >= 0) { reflectInvokeMethod(o,methods[j], new String [] {n.getNodeValue()}); } else { logger.warn("Unsupported attribute '" + n.getNodeName() + "' on <" + node.getNodeName() + "> tag"); } } catch (Exception e) { e.printStackTrace(); } } } return o; } private Image unmarshalImage(Node t, String baseDir) throws MalformedURLException, IOException { Image img = null; String source = getAttributeValue(t, "source"); if (source != null) { if (Util.checkRoot(source)) { source = makeUrl(source); } else { source = makeUrl(baseDir + source); } img = ImageIO.read(new URL(source)); // todo: check whether external images would also be faster drawn // todo: from a scaled instance, see below } else { NodeList nl = t.getChildNodes(); for (int i = 0; i < nl.getLength(); i++) { Node n = nl.item(i); if ("data".equals(n.getNodeName())) { Node cdata = n.getFirstChild(); if (cdata == null) { logger.warn("image <data> tag enclosed no " + "data. (empty data tag)"); } else { String sdata = cdata.getNodeValue(); char[] charArray = sdata.trim().toCharArray(); byte[] imageData = Base64.decode(charArray); img = ImageHelper.bytesToImage(imageData); // Deriving a scaled instance, even if it has the same // size, somehow makes drawing of the tiles a lot // faster on various systems (seen on Linux, Windows // and MacOS X). img = img.getScaledInstance( img.getWidth(null), img.getHeight(null), Image.SCALE_FAST); } break; } } } /* if (getAttributeValue(t, "set") != null) { TileSet ts = (TileSet)map.getTilesets().get( Integer.parseInt(getAttributeValue(t, "set"))); if (ts != null) { ts.addImage(img); } } */ return img; } private TileSet unmarshalTilesetFile(InputStream in, String filename) throws Exception { TileSet set = null; Node tsNode; Document tsDoc = null; DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance(); try { DocumentBuilder builder = factory.newDocumentBuilder(); //builder.setErrorHandler(new XMLErrorHandler()); tsDoc = builder.parse(in, "."); String xmlPathSave = xmlPath; if (filename.indexOf(File.separatorChar) >= 0) { xmlPath = filename.substring(0, filename.lastIndexOf(File.separatorChar) + 1); } NodeList tsNodeList = tsDoc.getElementsByTagName("tileset"); for (int itr = 0; (tsNode = tsNodeList.item(itr)) != null; itr++) { set = unmarshalTileset(tsNode); if (set.getSource() != null) { logger.warn("Recursive external Tilesets are not supported."); } set.setSource(filename); // NOTE: This is a deliberate break. multiple tilesets per TSX are // not supported yet (maybe never)... break; } xmlPath = xmlPathSave; } catch (SAXException e) { logger.error("Failed while loading "+filename+": "+e.getMessage()); //e.printStackTrace(); } return set; } private TileSet unmarshalTileset(Node t) throws Exception { String source = getAttributeValue(t, "source"); String basedir = getAttributeValue(t, "basedir"); int firstGid = getAttribute(t, "firstgid", 1); String tilesetBaseDir = xmlPath; if (basedir != null) { tilesetBaseDir = basedir; //makeUrl(basedir); } if (source != null) { String filename = tilesetBaseDir + source; //if (Util.checkRoot(source)) { // filename = makeUrl(source); //} TileSet ext = null; try { //just a little check for tricky people... String extention = source.substring(source.lastIndexOf('.') + 1); if (!"tsx".equals(extention.toLowerCase())) { logger.warn("tileset files should end in .tsx! ("+source+")"); } InputStream in = new URL(makeUrl(filename)).openStream(); ext = unmarshalTilesetFile(in, filename); } catch (FileNotFoundException fnf) { logger.error("Could not find external tileset file " + filename); } if (ext == null) { logger.error("tileset "+source+" was not loaded correctly!"); ext = new TileSet(); } ext.setFirstGid(firstGid); return ext; } else { int tileWidth = getAttribute(t, "tilewidth", map != null ? map.getTileWidth() : 0); int tileHeight = getAttribute(t, "tileheight", map != null ? map.getTileHeight() : 0); int tileSpacing = getAttribute(t, "spacing", 0); TileSet set = new TileSet(); set.setName(getAttributeValue(t, "name")); set.setBaseDir(basedir); set.setFirstGid(firstGid); boolean hasTilesetImage = false; NodeList children = t.getChildNodes(); for (int i = 0; i < children.getLength(); i++) { Node child = children.item(i); if (child.getNodeName().equalsIgnoreCase("image")) { if (hasTilesetImage) { logger.warn("Ignoring illegal image element after tileset image."); continue; } String imgSource = getAttributeValue(child, "source"); String id = getAttributeValue(child, "id"); String transStr = getAttributeValue(child, "trans"); if (imgSource != null && id == null) { // Not a shared image, but an entire set in one image // file. There should be only one image element in this // case. hasTilesetImage = true; // FIXME: importTileBitmap does not fully support URLs String sourcePath = imgSource; if (!Util.checkRoot(imgSource)) { sourcePath = tilesetBaseDir + imgSource; } logger.info("Importing " + sourcePath + "..."); if (transStr != null) { int colorInt = Integer.parseInt(transStr, 16); Color color = new Color(colorInt); set.setTransparentColor(color); } set.importTileBitmap(sourcePath, new BasicTileCutter( tileWidth, tileHeight, tileSpacing, 0)); } else { Image image = unmarshalImage(child, tilesetBaseDir); String idValue = getAttributeValue(child, "id"); int imageId = Integer.parseInt(idValue); set.addImage(image, imageId); } } else if (child.getNodeName().equalsIgnoreCase("tile")) { Tile tile = unmarshalTile(set, child, tilesetBaseDir); if (!hasTilesetImage || tile.getId() >= set.getMaxTileId()) { set.addTile(tile); } else { Tile myTile = set.getTile(tile.getId()); myTile.setProperties(tile.getProperties()); //TODO: there is the possibility here of overlaying images, // which some people may want } } } return set; } } private MapObject unmarshalObject(Node t) throws Exception { MapObject obj = null; try { obj = (MapObject)unmarshalClass(MapObject.class, t);
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -